aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2021-07-21 21:14:05 +0000
committerCy Schubert <cy@FreeBSD.org>2021-07-21 21:14:05 +0000
commit2f6c3ea9600b494d24cac5a38c1cea0ac192245e (patch)
treea03d50914bd459d06fc54300482332a32ca9b2be
parent40c7ff83e74eabba5a7e2caefeea12372b2d3f9a (diff)
downloadsrc-vendor/wpa.tar.gz
src-vendor/wpa.zip
Import wpa_supplicant/hostapd commit b4f7506ffvendor/wpa
-rw-r--r--src/ap/dfs.c15
-rw-r--r--src/ap/ieee802_11.c6
-rw-r--r--src/ap/wpa_auth_glue.c3
-rw-r--r--src/ap/wps_hostapd.c7
-rw-r--r--src/common/ieee802_11_common.c2
-rw-r--r--src/common/ieee802_11_defs.h1
-rw-r--r--src/common/qca-vendor.h44
-rw-r--r--src/drivers/driver.h6
-rw-r--r--src/drivers/driver_nl80211_event.c6
-rw-r--r--src/eap_server/eap_server_wsc.c8
-rw-r--r--src/p2p/p2p.c102
-rw-r--r--src/p2p/p2p.h17
-rw-r--r--src/p2p/p2p_i.h5
-rw-r--r--src/p2p/p2p_invitation.c5
-rw-r--r--src/p2p/p2p_utils.c39
-rw-r--r--src/rsn_supp/pmksa_cache.c10
-rw-r--r--src/rsn_supp/pmksa_cache.h6
-rw-r--r--src/rsn_supp/wpa.c18
-rw-r--r--src/rsn_supp/wpa.h11
-rw-r--r--src/wps/wps.h4
-rw-r--r--src/wps/wps_registrar.c6
-rw-r--r--tests/hwsim/test_multi_ap.py9
-rw-r--r--tests/hwsim/test_pasn.py4
-rw-r--r--tests/hwsim/test_sae.py16
-rw-r--r--wpa_supplicant/ap.c34
-rw-r--r--wpa_supplicant/ctrl_iface.c35
-rw-r--r--wpa_supplicant/dbus/dbus_new_handlers_p2p.c13
-rw-r--r--wpa_supplicant/events.c1
-rw-r--r--wpa_supplicant/p2p_supplicant.c292
-rw-r--r--wpa_supplicant/p2p_supplicant.h22
-rw-r--r--wpa_supplicant/scan.c1
-rw-r--r--wpa_supplicant/sme.c11
-rw-r--r--wpa_supplicant/wnm_sta.c4
-rw-r--r--wpa_supplicant/wpa_supplicant.c40
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h1
-rw-r--r--wpa_supplicant/wps_supplicant.c9
36 files changed, 669 insertions, 144 deletions
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index b990fb342388..03c99b175215 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -1228,7 +1228,9 @@ int hostapd_is_dfs_required(struct hostapd_iface *iface)
{
int n_chans, n_chans1, start_chan_idx, start_chan_idx1, res;
- if (!iface->conf->ieee80211h || !iface->current_mode ||
+ if ((!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
+ !iface->conf->ieee80211h) ||
+ !iface->current_mode ||
iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
return 0;
@@ -1279,6 +1281,8 @@ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
*/
int hostapd_handle_dfs_offload(struct hostapd_iface *iface)
{
+ int dfs_res;
+
wpa_printf(MSG_DEBUG, "%s: iface->cac_started: %d",
__func__, iface->cac_started);
@@ -1294,10 +1298,11 @@ int hostapd_handle_dfs_offload(struct hostapd_iface *iface)
return 1;
}
- if (ieee80211_is_dfs(iface->freq, iface->hw_features,
- iface->num_hw_features)) {
- wpa_printf(MSG_DEBUG, "%s: freq %d MHz requires DFS",
- __func__, iface->freq);
+ dfs_res = hostapd_is_dfs_required(iface);
+ if (dfs_res > 0) {
+ wpa_printf(MSG_DEBUG,
+ "%s: freq %d MHz requires DFS for %d chans",
+ __func__, iface->freq, dfs_res);
return 0;
}
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index b404e84affe5..22cce961063e 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -3943,8 +3943,10 @@ static void handle_auth(struct hostapd_data *hapd,
fail:
reply_res = send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, auth_alg,
- auth_transaction + 1, resp, resp_ies,
- resp_ies_len, "handle-auth");
+ auth_alg == WLAN_AUTH_SAE ?
+ auth_transaction : auth_transaction + 1,
+ resp, resp_ies, resp_ies_len,
+ "handle-auth");
if (sta && sta->added_unassoc && (resp != WLAN_STATUS_SUCCESS ||
reply_res != WLAN_STATUS_SUCCESS)) {
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index 7ca292530dc1..3e992155395e 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -1553,7 +1553,8 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
return -1;
}
- hapd->ptksa = ptksa_cache_init();
+ if (!hapd->ptksa)
+ hapd->ptksa = ptksa_cache_init();
if (!hapd->ptksa) {
wpa_printf(MSG_ERROR, "Failed to allocate PTKSA cache");
return -1;
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index e97dbf996749..9f22e39a2e6a 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -1172,6 +1172,8 @@ int hostapd_init_wps(struct hostapd_data *hapd,
wps->auth_types |= WPS_AUTH_WPA2PSK;
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X)
wps->auth_types |= WPS_AUTH_WPA2;
+ if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE)
+ wps->auth_types |= WPS_AUTH_WPA2PSK;
if (conf->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
WPA_CIPHER_CCMP_256 |
@@ -1328,6 +1330,11 @@ int hostapd_init_wps(struct hostapd_data *hapd,
hostapd_register_probereq_cb(hapd, hostapd_wps_probe_req_rx, hapd);
+#ifdef CONFIG_P2P
+ if ((hapd->conf->p2p & P2P_ENABLED) &&
+ is_6ghz_op_class(hapd->iconf->op_class))
+ wps->use_passphrase = true;
+#endif /* CONFIG_P2P */
hapd->wps = wps;
bin_clear_free(multi_ap_netw_key, 2 * PMK_LEN);
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index 96681843e258..3e5cfb01d565 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -1894,7 +1894,7 @@ const struct oper_class_map global_op_class[] = {
*/
{ HOSTAPD_MODE_IEEE80211A, 128, 36, 177, 4, BW80, P2P_SUPP },
{ HOSTAPD_MODE_IEEE80211A, 129, 36, 177, 4, BW160, P2P_SUPP },
- { HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, NO_P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, P2P_SUPP },
{ HOSTAPD_MODE_IEEE80211A, 132, 1, 233, 8, BW40, NO_P2P_SUPP },
{ HOSTAPD_MODE_IEEE80211A, 133, 1, 233, 16, BW80, NO_P2P_SUPP },
{ HOSTAPD_MODE_IEEE80211A, 134, 1, 233, 32, BW160, NO_P2P_SUPP },
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 7d2f36b8f1e6..519a13b1d064 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -1657,6 +1657,7 @@ enum p2p_attr_id {
#define P2P_DEV_CAPAB_INFRA_MANAGED BIT(3)
#define P2P_DEV_CAPAB_DEVICE_LIMIT BIT(4)
#define P2P_DEV_CAPAB_INVITATION_PROCEDURE BIT(5)
+#define P2P_DEV_CAPAB_6GHZ_BAND_CAPABLE BIT(6)
/* P2P Capability - Group Capability bitmap */
#define P2P_GROUP_CAPAB_GROUP_OWNER BIT(0)
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index ce588cc00a59..47666f04ae7c 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -1730,11 +1730,22 @@ enum qca_vendor_attr_tsf_cmd {
* @QCA_TSF_CAPTURE: Initiate TSF Capture
* @QCA_TSF_GET: Get TSF capture value
* @QCA_TSF_SYNC_GET: Initiate TSF capture and return with captured value
+ * @QCA_TSF_AUTO_REPORT_ENABLE: Used in STA mode only. Once set, the target
+ * will automatically send TSF report to the host. To query
+ * QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY, this operation needs to be
+ * initiated first.
+ * @QCA_TSF_AUTO_REPORT_DISABLE: Used in STA mode only. Once set, the target
+ * will not automatically send TSF report to the host. If
+ * QCA_TSF_AUTO_REPORT_ENABLE is initiated and
+ * QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY is not queried anymore, this
+ * operation needs to be initiated.
*/
enum qca_tsf_cmd {
QCA_TSF_CAPTURE,
QCA_TSF_GET,
QCA_TSF_SYNC_GET,
+ QCA_TSF_AUTO_REPORT_ENABLE,
+ QCA_TSF_AUTO_REPORT_DISABLE,
};
/**
@@ -3867,6 +3878,10 @@ enum qca_wlan_vendor_attr_ll_stats_results {
* QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO.
*/
QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_RX_TIME = 85,
+ /* u8 value representing the channel load percentage. Possible values
+ * are 0-100.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_LOAD_PERCENTAGE = 86,
/* keep last */
QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX =
@@ -8120,6 +8135,29 @@ enum qca_wlan_vendor_attr_wifi_test_config {
*/
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_KEEP_ALIVE_FRAME_TYPE = 53,
+ /* 8-bit unsigned value to configure the driver to use scan request
+ * BSSID value in Probe Request frame RA(A1) during the scan. The
+ * driver saves this configuration and applies this setting to all user
+ * space scan requests until the setting is cleared. If this
+ * configuration is set, the driver uses the BSSID value from the scan
+ * request to set the RA(A1) in the Probe Request frames during the
+ * scan.
+ *
+ * 0 - Default behavior uses the broadcast RA in Probe Request frames.
+ * 1 - Uses the scan request BSSID in RA in Probe Request frames.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_USE_BSSID_IN_PROBE_REQ_RA = 54,
+
+ /* 8-bit unsigned value to configure the driver to enable/disable the
+ * BSS max idle period support.
+ *
+ * 0 - Disable the BSS max idle support.
+ * 1 - Enable the BSS max idle support.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD_ENABLE = 55,
+
/* keep last */
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX =
@@ -10369,6 +10407,11 @@ enum qca_vendor_wlan_sta_guard_interval {
* failed roam invoke. Different roam invoke failure reason codes
* are specified in enum qca_vendor_roam_invoke_fail_reasons. This can be
* queried either in connected state or disconnected state.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY: u32, used in STA mode only.
+ * This represents the average congestion duration of uplink frames in MAC
+ * queue in unit of ms. This can be queried either in connected state or
+ * disconnected state.
*/
enum qca_wlan_vendor_attr_get_sta_info {
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_INVALID = 0,
@@ -10421,6 +10464,7 @@ enum qca_wlan_vendor_attr_get_sta_info {
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_TRIGGER_REASON = 47,
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_FAIL_REASON = 48,
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_INVOKE_FAIL_REASON = 49,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY = 50,
/* keep last */
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_AFTER_LAST,
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 561882d0d024..804ac6806f61 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -645,6 +645,12 @@ struct wpa_driver_scan_params {
*/
unsigned int oce_scan:1;
+ /**
+ * p2p_include_6ghz - Include 6 GHz channels for P2P full scan
+ *
+ */
+ unsigned int p2p_include_6ghz:1;
+
/*
* NOTE: Whenever adding new parameters here, please make sure
* wpa_scan_clone_params() and wpa_scan_free_params() get updated with
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index d19586f06ead..0f0a01d0180b 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -1329,7 +1329,7 @@ static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
struct nlattr *nl;
int rem;
struct scan_info *info;
-#define MAX_REPORT_FREQS 50
+#define MAX_REPORT_FREQS 100
int freqs[MAX_REPORT_FREQS];
int num_freqs = 0;
@@ -1361,7 +1361,7 @@ static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
}
}
if (tb[NL80211_ATTR_SCAN_FREQUENCIES]) {
- char msg[300], *pos, *end;
+ char msg[500], *pos, *end;
int res;
pos = msg;
@@ -2273,7 +2273,7 @@ static void send_vendor_scan_event(struct wpa_driver_nl80211_data *drv,
}
if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES]) {
- char msg[300], *pos, *end;
+ char msg[500], *pos, *end;
int res;
pos = msg;
diff --git a/src/eap_server/eap_server_wsc.c b/src/eap_server/eap_server_wsc.c
index fc70cf1962db..a162deb9ef6b 100644
--- a/src/eap_server/eap_server_wsc.c
+++ b/src/eap_server/eap_server_wsc.c
@@ -132,9 +132,11 @@ static void * eap_wsc_init(struct eap_sm *sm)
cfg.peer_addr = sm->peer_addr;
#ifdef CONFIG_P2P
if (sm->assoc_p2p_ie) {
- wpa_printf(MSG_DEBUG, "EAP-WSC: Prefer PSK format for P2P "
- "client");
- cfg.use_psk_key = 1;
+ if (!sm->cfg->wps->use_passphrase) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-WSC: Prefer PSK format for non-6 GHz P2P client");
+ cfg.use_psk_key = 1;
+ }
cfg.p2p_dev_addr = p2p_get_go_dev_addr(sm->assoc_p2p_ie);
}
#endif /* CONFIG_P2P */
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 1aa98f1a877a..9ac505735cbb 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -1035,7 +1035,7 @@ static void p2p_search(struct p2p_data *p2p)
res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq,
p2p->num_req_dev_types, p2p->req_dev_types,
- p2p->find_dev_id, pw_id);
+ p2p->find_dev_id, pw_id, p2p->include_6ghz);
if (res < 0) {
p2p_dbg(p2p, "Scan request schedule failed");
p2p_continue_find(p2p);
@@ -1159,7 +1159,7 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout,
enum p2p_discovery_type type,
unsigned int num_req_dev_types, const u8 *req_dev_types,
const u8 *dev_id, unsigned int search_delay,
- u8 seek_count, const char **seek, int freq)
+ u8 seek_count, const char **seek, int freq, bool include_6ghz)
{
int res;
struct os_reltime start;
@@ -1184,7 +1184,7 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout,
p2p->find_dev_id = p2p->find_dev_id_buf;
} else
p2p->find_dev_id = NULL;
-
+ p2p->include_6ghz = p2p_wfd_enabled(p2p) && include_6ghz;
if (seek_count == 0 || !seek) {
/* Not an ASP search */
p2p->p2ps_seek = 0;
@@ -1260,7 +1260,8 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout,
P2P_SCAN_SPECIFIC, freq,
p2p->num_req_dev_types,
p2p->req_dev_types, dev_id,
- DEV_PW_DEFAULT);
+ DEV_PW_DEFAULT,
+ p2p->include_6ghz);
break;
}
/* fall through */
@@ -1268,13 +1269,13 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout,
res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0,
p2p->num_req_dev_types,
p2p->req_dev_types, dev_id,
- DEV_PW_DEFAULT);
+ DEV_PW_DEFAULT, p2p->include_6ghz);
break;
case P2P_FIND_ONLY_SOCIAL:
res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0,
p2p->num_req_dev_types,
p2p->req_dev_types, dev_id,
- DEV_PW_DEFAULT);
+ DEV_PW_DEFAULT, p2p->include_6ghz);
break;
default:
return -1;
@@ -1396,8 +1397,8 @@ static int p2p_prepare_channel_pref(struct p2p_data *p2p,
p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
} else {
- os_memcpy(&p2p->channels, &p2p->cfg->channels,
- sizeof(struct p2p_channels));
+ p2p_copy_channels(&p2p->channels, &p2p->cfg->channels,
+ p2p->allow_6ghz);
}
return 0;
@@ -1411,6 +1412,7 @@ static void p2p_prepare_channel_best(struct p2p_data *p2p)
const int op_classes_ht40[] = { 126, 127, 116, 117, 0 };
const int op_classes_vht[] = { 128, 0 };
const int op_classes_edmg[] = { 181, 182, 183, 0 };
+ const int op_classes_6ghz[] = { 131, 0 };
p2p_dbg(p2p, "Prepare channel best");
@@ -1447,6 +1449,12 @@ static void p2p_prepare_channel_best(struct p2p_data *p2p)
0) {
p2p_dbg(p2p, "Select possible EDMG channel (op_class %u channel %u) as operating channel preference",
p2p->op_reg_class, p2p->op_channel);
+ } else if (p2p->allow_6ghz &&
+ (p2p_channel_select(&p2p->cfg->channels, op_classes_6ghz,
+ &p2p->op_reg_class, &p2p->op_channel) ==
+ 0)) {
+ p2p_dbg(p2p, "Select possible 6 GHz channel (op_class %u channel %u) as operating channel preference",
+ p2p->op_reg_class, p2p->op_channel);
} else if (p2p_channel_select(&p2p->cfg->channels, op_classes_vht,
&p2p->op_reg_class, &p2p->op_channel) ==
0) {
@@ -1484,8 +1492,7 @@ static void p2p_prepare_channel_best(struct p2p_data *p2p)
p2p->op_channel, p2p->op_reg_class);
}
- os_memcpy(&p2p->channels, &p2p->cfg->channels,
- sizeof(struct p2p_channels));
+ p2p_copy_channels(&p2p->channels, &p2p->cfg->channels, p2p->allow_6ghz);
}
@@ -1568,9 +1575,10 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
p2p_dbg(p2p, "Request to start group negotiation - peer=" MACSTR
" GO Intent=%d Intended Interface Address=" MACSTR
" wps_method=%d persistent_group=%d pd_before_go_neg=%d "
- "oob_pw_id=%u",
+ "oob_pw_id=%u allow_6ghz=%d",
MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
- wps_method, persistent_group, pd_before_go_neg, oob_pw_id);
+ wps_method, persistent_group, pd_before_go_neg, oob_pw_id,
+ p2p->allow_6ghz);
dev = p2p_get_device(p2p, peer_addr);
if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
@@ -1668,9 +1676,9 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
p2p_dbg(p2p, "Request to authorize group negotiation - peer=" MACSTR
" GO Intent=%d Intended Interface Address=" MACSTR
- " wps_method=%d persistent_group=%d oob_pw_id=%u",
+ " wps_method=%d persistent_group=%d oob_pw_id=%u allow_6ghz=%d",
MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
- wps_method, persistent_group, oob_pw_id);
+ wps_method, persistent_group, oob_pw_id, p2p->allow_6ghz);
dev = p2p_get_device(p2p, peer_addr);
if (dev == NULL) {
@@ -5575,3 +5583,69 @@ struct wpabuf * p2p_build_probe_resp_template(struct p2p_data *p2p,
return buf;
}
+
+
+bool p2p_is_peer_6ghz_capab(struct p2p_data *p2p, const u8 *addr)
+{
+ struct p2p_device *dev;
+
+ dev = p2p_get_device(p2p, addr);
+ if (!dev)
+ return false;
+
+ return !!(dev->info.dev_capab & P2P_DEV_CAPAB_6GHZ_BAND_CAPABLE);
+}
+
+
+void p2p_set_6ghz_dev_capab(struct p2p_data *p2p, bool allow_6ghz)
+{
+ p2p->p2p_6ghz_capable = allow_6ghz;
+ p2p->allow_6ghz = allow_6ghz;
+ p2p_dbg(p2p, "Set 6 GHz capability to %d", allow_6ghz);
+
+ if (allow_6ghz)
+ p2p->dev_capab |= P2P_DEV_CAPAB_6GHZ_BAND_CAPABLE;
+ else
+ p2p->dev_capab &= ~P2P_DEV_CAPAB_6GHZ_BAND_CAPABLE;
+}
+
+
+bool is_p2p_6ghz_capable(struct p2p_data *p2p)
+{
+ return p2p->p2p_6ghz_capable;
+}
+
+
+bool p2p_wfd_enabled(struct p2p_data *p2p)
+{
+#ifdef CONFIG_WIFI_DISPLAY
+ return p2p->wfd_ie_probe_req != NULL;
+#else /* CONFIG_WIFI_DISPLAY */
+ return false;
+#endif /* CONFIG_WIFI_DISPLAY */
+}
+
+
+bool p2p_peer_wfd_enabled(struct p2p_data *p2p, const u8 *peer_addr)
+{
+#ifdef CONFIG_WIFI_DISPLAY
+ struct p2p_device *dev;
+
+ dev = p2p_get_device(p2p, peer_addr);
+ return dev && dev->info.wfd_subelems != NULL;
+#else /* CONFIG_WIFI_DISPLAY */
+ return false;
+#endif /* CONFIG_WIFI_DISPLAY */
+}
+
+
+bool is_p2p_allow_6ghz(struct p2p_data *p2p)
+{
+ return p2p->allow_6ghz;
+}
+
+
+void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value)
+{
+ p2p->allow_6ghz = value;
+}
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 762bd40bea8b..f606fbb14a81 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -612,6 +612,7 @@ struct p2p_config {
* @req_dev_types: Array containing requested device types
* @dev_id: Device ID to search for or %NULL to find all devices
* @pw_id: Device Password ID
+ * @include_6ghz: Include 6 GHz channels in P2P scan
* Returns: 0 on success, -1 on failure
*
* This callback function is used to request a P2P scan or search
@@ -635,7 +636,8 @@ struct p2p_config {
*/
int (*p2p_scan)(void *ctx, enum p2p_scan_type type, int freq,
unsigned int num_req_dev_types,
- const u8 *req_dev_types, const u8 *dev_id, u16 pw_id);
+ const u8 *req_dev_types, const u8 *dev_id, u16 pw_id,
+ bool include_6ghz);
/**
* send_probe_resp - Transmit a Probe Response frame
@@ -1243,13 +1245,15 @@ enum p2p_discovery_type {
* P2P_FIND_START_WITH_FULL behavior. 0 = Use normal full scan.
* If p2p_find is already in progress, this parameter is ignored and full
* scan will be executed.
+ * @include_6ghz: Include 6 GHz channels in P2P find
* Returns: 0 on success, -1 on failure
*/
int p2p_find(struct p2p_data *p2p, unsigned int timeout,
enum p2p_discovery_type type,
unsigned int num_req_dev_types, const u8 *req_dev_types,
const u8 *dev_id, unsigned int search_delay,
- u8 seek_count, const char **seek_string, int freq);
+ u8 seek_count, const char **seek_string, int freq,
+ bool include_6ghz);
/**
* p2p_notify_scan_trigger_status - Indicate scan trigger status
@@ -2411,4 +2415,13 @@ int p2p_group_get_common_freqs(struct p2p_group *group, int *common_freqs,
struct wpabuf * p2p_build_probe_resp_template(struct p2p_data *p2p,
unsigned int freq);
+void p2p_set_6ghz_dev_capab(struct p2p_data *p2p, bool allow_6ghz);
+bool is_p2p_6ghz_capable(struct p2p_data *p2p);
+bool p2p_is_peer_6ghz_capab(struct p2p_data *p2p, const u8 *addr);
+bool p2p_peer_wfd_enabled(struct p2p_data *p2p, const u8 *peer_addr);
+bool p2p_wfd_enabled(struct p2p_data *p2p);
+bool is_p2p_allow_6ghz(struct p2p_data *p2p);
+void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value);
+int p2p_remove_6ghz_channels(unsigned int *pref_freq_list, int size);
+
#endif /* P2P_H */
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index 4195c5f07dd1..8220e85506a3 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -548,6 +548,9 @@ struct p2p_data {
/* Override option for preferred operating channel in GO Negotiation */
u8 override_pref_op_class;
u8 override_pref_channel;
+ bool p2p_6ghz_capable;
+ bool include_6ghz;
+ bool allow_6ghz;
};
/**
@@ -698,6 +701,8 @@ int p2p_channel_random_social(struct p2p_channels *chans, u8 *op_class,
u8 *op_channel,
struct wpa_freq_range_list *avoid_list,
struct wpa_freq_range_list *disallow_list);
+void p2p_copy_channels(struct p2p_channels *dst, const struct p2p_channels *src,
+ bool allow_6ghz);
/* p2p_parse.c */
void p2p_copy_filter_devname(char *dst, size_t dst_len,
diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c
index 77d662a47ae2..ab0072219d2e 100644
--- a/src/p2p/p2p_invitation.c
+++ b/src/p2p/p2p_invitation.c
@@ -653,8 +653,9 @@ int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role,
struct p2p_device *dev;
p2p_dbg(p2p, "Request to invite peer " MACSTR " role=%d persistent=%d "
- "force_freq=%u",
- MAC2STR(peer), role, persistent_group, force_freq);
+ "force_freq=%u allow_6ghz=%d",
+ MAC2STR(peer), role, persistent_group, force_freq,
+ p2p->allow_6ghz);
if (bssid)
p2p_dbg(p2p, "Invitation for BSSID " MACSTR, MAC2STR(bssid));
if (go_dev_addr) {
diff --git a/src/p2p/p2p_utils.c b/src/p2p/p2p_utils.c
index 1a62a44a2df3..7d21f68819c7 100644
--- a/src/p2p/p2p_utils.c
+++ b/src/p2p/p2p_utils.c
@@ -496,3 +496,42 @@ int p2p_channels_to_freqs(const struct p2p_channels *channels, int *freq_list,
return idx;
}
+
+
+void p2p_copy_channels(struct p2p_channels *dst,
+ const struct p2p_channels *src, bool allow_6ghz)
+{
+ size_t i, j;
+
+ if (allow_6ghz) {
+ os_memcpy(dst, src, sizeof(struct p2p_channels));
+ return;
+ }
+
+ for (i = 0, j = 0; i < P2P_MAX_REG_CLASSES; i++) {
+ if (is_6ghz_op_class(src->reg_class[i].reg_class))
+ continue;
+ os_memcpy(&dst->reg_class[j], &src->reg_class[i],
+ sizeof(struct p2p_reg_class));
+ j++;
+ }
+ dst->reg_classes = j;
+}
+
+
+int p2p_remove_6ghz_channels(unsigned int *pref_freq_list, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ if (is_6ghz_freq(pref_freq_list[i])) {
+ wpa_printf(MSG_DEBUG, "P2P: Remove 6 GHz channel %d",
+ pref_freq_list[i]);
+ size--;
+ os_memmove(&pref_freq_list[i], &pref_freq_list[i + 1],
+ (size - i) * sizeof(pref_freq_list[0]));
+ i--;
+ }
+ }
+ return i;
+}
diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c
index cb2a8674a81b..97a01a2f81e8 100644
--- a/src/rsn_supp/pmksa_cache.c
+++ b/src/rsn_supp/pmksa_cache.c
@@ -212,7 +212,8 @@ pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa,
"that was based on the old PMK");
if (!pos->opportunistic)
pmksa_cache_flush(pmksa, entry->network_ctx,
- pos->pmk, pos->pmk_len);
+ pos->pmk, pos->pmk_len,
+ false);
pmksa_cache_free_entry(pmksa, pos, PMKSA_REPLACE);
break;
}
@@ -282,9 +283,11 @@ pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa,
* @network_ctx: Network configuration context or %NULL to flush all entries
* @pmk: PMK to match for or %NULL to match all PMKs
* @pmk_len: PMK length
+ * @external_only: Flush only PMKSA cache entries configured by external
+ * applications
*/
void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
- const u8 *pmk, size_t pmk_len)
+ const u8 *pmk, size_t pmk_len, bool external_only)
{
struct rsn_pmksa_cache_entry *entry, *prev = NULL, *tmp;
int removed = 0;
@@ -295,7 +298,8 @@ void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
network_ctx == NULL) &&
(pmk == NULL ||
(pmk_len == entry->pmk_len &&
- os_memcmp(pmk, entry->pmk, pmk_len) == 0))) {
+ os_memcmp(pmk, entry->pmk, pmk_len) == 0)) &&
+ (!external_only || entry->external)) {
wpa_printf(MSG_DEBUG, "RSN: Flush PMKSA cache entry "
"for " MACSTR, MAC2STR(entry->aa));
if (prev)
diff --git a/src/rsn_supp/pmksa_cache.h b/src/rsn_supp/pmksa_cache.h
index 83faa05844d6..ae7bc13fa118 100644
--- a/src/rsn_supp/pmksa_cache.h
+++ b/src/rsn_supp/pmksa_cache.h
@@ -43,6 +43,7 @@ struct rsn_pmksa_cache_entry {
*/
void *network_ctx;
int opportunistic;
+ bool external;
};
struct rsn_pmksa_cache;
@@ -84,7 +85,7 @@ struct rsn_pmksa_cache_entry *
pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa,
void *network_ctx, const u8 *aa, int akmp);
void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
- const u8 *pmk, size_t pmk_len);
+ const u8 *pmk, size_t pmk_len, bool external_only);
#else /* IEEE8021X_EAPOL */
@@ -157,7 +158,8 @@ static inline int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
static inline void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa,
void *network_ctx,
- const u8 *pmk, size_t pmk_len)
+ const u8 *pmk, size_t pmk_len,
+ bool external_only)
{
}
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 78e2380b15e8..e01cd52177d2 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -2345,6 +2345,16 @@ void wpa_sm_aborted_cached(struct wpa_sm *sm)
}
+void wpa_sm_aborted_external_cached(struct wpa_sm *sm)
+{
+ if (sm && sm->cur_pmksa && sm->cur_pmksa->external) {
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "RSN: Cancelling external PMKSA caching attempt");
+ sm->cur_pmksa = NULL;
+ }
+}
+
+
static void wpa_eapol_key_dump(struct wpa_sm *sm,
const struct wpa_eapol_key *key,
unsigned int key_data_len,
@@ -3865,7 +3875,13 @@ void wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr)
void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx)
{
- pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0);
+ pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0, false);
+}
+
+
+void wpa_sm_external_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx)
+{
+ pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0, true);
}
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index f377acba2f23..ff8a85b6e29b 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -180,6 +180,7 @@ int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
struct wpa_ie_data *data);
void wpa_sm_aborted_cached(struct wpa_sm *sm);
+void wpa_sm_aborted_external_cached(struct wpa_sm *sm);
int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
const u8 *buf, size_t len);
int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data);
@@ -205,6 +206,7 @@ int wpa_sm_has_ptk_installed(struct wpa_sm *sm);
void wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr);
void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx);
+void wpa_sm_external_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx);
int wpa_sm_get_p2p_ip_addr(struct wpa_sm *sm, u8 *buf);
@@ -353,6 +355,10 @@ static inline void wpa_sm_aborted_cached(struct wpa_sm *sm)
{
}
+static inline void wpa_sm_aborted_external_cached(struct wpa_sm *sm)
+{
+}
+
static inline int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
const u8 *buf, size_t len)
{
@@ -392,6 +398,11 @@ static inline void wpa_sm_update_replay_ctr(struct wpa_sm *sm,
{
}
+static inline void wpa_sm_external_pmksa_cache_flush(struct wpa_sm *sm,
+ void *network_ctx)
+{
+}
+
static inline void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm,
void *network_ctx)
{
diff --git a/src/wps/wps.h b/src/wps/wps.h
index 6a12255c8a68..fed3e284895f 100644
--- a/src/wps/wps.h
+++ b/src/wps/wps.h
@@ -841,6 +841,10 @@ struct wps_context {
struct wpabuf *ap_nfc_dh_pubkey;
struct wpabuf *ap_nfc_dh_privkey;
struct wpabuf *ap_nfc_dev_pw;
+
+ /* Whether to send WPA2-PSK passphrase as a passphrase instead of PSK
+ * for WPA3-Personal transition mode needs. */
+ bool use_passphrase;
};
struct wps_registrar *
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index 45f7e947e0fd..173fbbd68aa0 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -1753,8 +1753,10 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
wpa_snprintf_hex(hex, sizeof(hex), wps->wps->psk, PMK_LEN);
os_memcpy(wps->cred.key, hex, PMK_LEN * 2);
wps->cred.key_len = PMK_LEN * 2;
- } else if (!wps->wps->registrar->force_per_enrollee_psk &&
- wps->wps->network_key) {
+ } else if ((!wps->wps->registrar->force_per_enrollee_psk ||
+ wps->wps->use_passphrase) && wps->wps->network_key) {
+ wpa_printf(MSG_DEBUG,
+ "WPS: Use passphrase format for Network key");
os_memcpy(wps->cred.key, wps->wps->network_key,
wps->wps->network_key_len);
wps->cred.key_len = wps->wps->network_key_len;
diff --git a/tests/hwsim/test_multi_ap.py b/tests/hwsim/test_multi_ap.py
index ca8ea3a31f90..99db14ebfae9 100644
--- a/tests/hwsim/test_multi_ap.py
+++ b/tests/hwsim/test_multi_ap.py
@@ -100,6 +100,11 @@ def test_multi_ap_fronthaul_on_ap(dev, apdev):
if "CTRL-EVENT-DISCONNECTED" not in ev:
raise Exception("Unexpected connection result")
+def remove_apdev(dev, ifname):
+ hglobal = hostapd.HostapdGlobal()
+ hglobal.remove(ifname)
+ dev.cmd_execute(['iw', ifname, 'del'])
+
def run_multi_ap_wps(dev, apdev, params, params_backhaul=None, add_apdev=False,
run_csa=False, allow_csa_fail=False):
"""Helper for running Multi-AP WPS tests
@@ -219,10 +224,10 @@ def run_multi_ap_wps(dev, apdev, params, params_backhaul=None, add_apdev=False,
raise Exception("Received disconnection event instead of channel switch event")
if add_apdev:
- dev[0].cmd_execute(['iw', wpas_apdev['ifname'], 'del'])
+ remove_apdev(dev[0], wpas_apdev['ifname'])
except:
if wpas_apdev:
- dev[0].cmd_execute(['iw', wpas_apdev['ifname'], 'del'])
+ remove_apdev(dev[0], wpas_apdev['ifname'])
raise
return hapd
diff --git a/tests/hwsim/test_pasn.py b/tests/hwsim/test_pasn.py
index c8bcd63f6ac7..6f7a806f5c46 100644
--- a/tests/hwsim/test_pasn.py
+++ b/tests/hwsim/test_pasn.py
@@ -680,6 +680,8 @@ def test_pasn_ft_eap_sha384(dev, apdev):
def test_pasn_sta_mic_error(dev, apdev):
"""PASN authentication with WPA2/CCMP AP with corrupted MIC on station"""
+ check_pasn_capab(dev[0])
+
params = pasn_ap_params("PASN", "CCMP", "19")
hapd = hostapd.add_ap(apdev[0], params)
@@ -697,6 +699,8 @@ def test_pasn_sta_mic_error(dev, apdev):
def test_pasn_ap_mic_error(dev, apdev):
"""PASN authentication with WPA2/CCMP AP with corrupted MIC on AP"""
+ check_pasn_capab(dev[0])
+
params = pasn_ap_params("PASN", "CCMP", "19")
hapd0 = hostapd.add_ap(apdev[0], params)
diff --git a/tests/hwsim/test_sae.py b/tests/hwsim/test_sae.py
index 159678e0c7be..9925d98f3a7c 100644
--- a/tests/hwsim/test_sae.py
+++ b/tests/hwsim/test_sae.py
@@ -2775,3 +2775,19 @@ def test_sae_ocv_pmk_failure(dev, apdev):
raise Exception("hostapd did not report correct PMK after disconnection")
if pmk_w2 != pmk_w:
raise Exception("wpa_supplicant did not report correct PMK after disconnection")
+
+def test_sae_reject(dev, apdev):
+ """SAE and AP rejecting connection"""
+ check_sae_capab(dev[0])
+ params = hostapd.wpa2_params(ssid="test-sae",
+ passphrase="12345678")
+ params['wpa_key_mgmt'] = 'SAE'
+ params['max_num_sta'] = '0'
+ hapd = hostapd.add_ap(apdev[0], params)
+ dev[0].set("sae_groups", "")
+ id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412", wait_connect=False)
+ if not dev[0].wait_event(["CTRL-EVENT-AUTH-REJECT"], timeout=10):
+ raise Exception("Authentication rejection not reported")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index cfefa48d443e..cdf0ed5c7b5f 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -109,13 +109,15 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
switch (hostapd_get_oper_chwidth(conf)) {
case CHANWIDTH_80MHZ:
case CHANWIDTH_80P80MHZ:
- center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel);
+ center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel,
+ conf->op_class);
wpa_printf(MSG_DEBUG,
"VHT center channel %u for 80 or 80+80 MHz bandwidth",
center_chan);
break;
case CHANWIDTH_160MHZ:
- center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel);
+ center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel,
+ conf->op_class);
wpa_printf(MSG_DEBUG,
"VHT center channel %u for 160 MHz bandwidth",
center_chan);
@@ -127,15 +129,25 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
* not supported.
*/
hostapd_set_oper_chwidth(conf, CHANWIDTH_160MHZ);
- center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel);
+ ieee80211_freq_to_channel_ext(ssid->frequency, 0,
+ conf->vht_oper_chwidth,
+ &conf->op_class,
+ &conf->channel);
+ center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel,
+ conf->op_class);
if (center_chan && is_chanwidth160_supported(mode, conf)) {
wpa_printf(MSG_DEBUG,
"VHT center channel %u for auto-selected 160 MHz bandwidth",
center_chan);
} else {
hostapd_set_oper_chwidth(conf, CHANWIDTH_80MHZ);
+ ieee80211_freq_to_channel_ext(ssid->frequency, 0,
+ conf->vht_oper_chwidth,
+ &conf->op_class,
+ &conf->channel);
center_chan = wpas_p2p_get_vht80_center(wpa_s, mode,
- channel);
+ channel,
+ conf->op_class);
wpa_printf(MSG_DEBUG,
"VHT center channel %u for auto-selected 80 MHz bandwidth",
center_chan);
@@ -183,9 +195,15 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
struct hostapd_config *conf)
{
- conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
- &conf->channel);
-
+ conf->hw_mode = ieee80211_freq_to_channel_ext(ssid->frequency, 0,
+ ssid->max_oper_chwidth,
+ &conf->op_class,
+ &conf->channel);
+ /* ssid->max_oper_chwidth is not valid in all cases, so fall back to the
+ * less specific mechanism, if needed, at least for now */
+ if (conf->hw_mode == NUM_HOSTAPD_MODES)
+ conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
+ &conf->channel);
if (conf->hw_mode == NUM_HOSTAPD_MODES) {
wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
ssid->frequency);
@@ -874,6 +892,8 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
params.wpa_proto = ssid->proto;
if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
+ else if (ssid->key_mgmt & WPA_KEY_MGMT_SAE)
+ wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
else
wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
params.key_mgmt_suite = wpa_s->key_mgmt;
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index ba91cfb11d14..8a6a829b6665 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -5723,12 +5723,16 @@ static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL;
u8 seek_count = 0;
int freq = 0;
+ bool include_6ghz = false;
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
wpa_dbg(wpa_s, MSG_INFO,
"Reject P2P_FIND since interface is disabled");
return -1;
}
+
+ if (os_strstr(cmd, " include_6ghz"))
+ include_6ghz = true;
if (os_strstr(cmd, "type=social"))
type = P2P_FIND_ONLY_SOCIAL;
else if (os_strstr(cmd, "type=progressive"))
@@ -5788,7 +5792,8 @@ static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
}
return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
- _dev_id, search_delay, seek_count, seek, freq);
+ _dev_id, search_delay, seek_count, seek, freq,
+ include_6ghz);
}
@@ -6041,6 +6046,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL;
size_t group_ssid_len = 0;
int he;
+ bool allow_6ghz;
if (!wpa_s->global->p2p_init_wpa_s)
return -1;
@@ -6078,6 +6084,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
}
}
join = os_strstr(pos, " join") != NULL;
+ allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL;
auth = os_strstr(pos, " auth") != NULL;
automatic = os_strstr(pos, " auto") != NULL;
pd = os_strstr(pos, " provdisc") != NULL;
@@ -6157,7 +6164,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
persistent_group, automatic, join,
auth, go_intent, freq, freq2, persistent_id,
pd, ht40, vht, max_oper_chwidth, he, edmg,
- group_ssid, group_ssid_len);
+ group_ssid, group_ssid_len, allow_6ghz);
if (new_pin == -2) {
os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
return 25;
@@ -6714,6 +6721,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
int freq = 0, pref_freq = 0;
int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0;
int edmg;
+ bool allow_6ghz;
id = atoi(cmd);
pos = os_strstr(cmd, " peer=");
@@ -6765,8 +6773,11 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
if (max_oper_chwidth < 0)
return -1;
+ allow_6ghz = os_strstr(cmd, " allow_6ghz") != NULL;
+
return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
- max_oper_chwidth, pref_freq, he, edmg);
+ max_oper_chwidth, pref_freq, he, edmg,
+ allow_6ghz);
}
@@ -6774,6 +6785,7 @@ static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
{
char *pos;
u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
+ bool allow_6ghz;
pos = os_strstr(cmd, " peer=");
if (!pos)
@@ -6786,6 +6798,8 @@ static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
return -1;
}
+ allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL;
+
pos = os_strstr(pos, " go_dev_addr=");
if (pos) {
pos += 13;
@@ -6797,7 +6811,7 @@ static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
go_dev = go_dev_addr;
}
- return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
+ return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev, allow_6ghz);
}
@@ -6815,7 +6829,7 @@ static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
int id, int freq, int vht_center_freq2,
int ht40, int vht, int vht_chwidth,
- int he, int edmg)
+ int he, int edmg, bool allow_6ghz)
{
struct wpa_ssid *ssid;
@@ -6830,13 +6844,14 @@ static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
vht_center_freq2, 0, ht40, vht,
vht_chwidth, he, edmg,
- NULL, 0, 0);
+ NULL, 0, 0, allow_6ghz);
}
static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
{
int freq = 0, persistent = 0, group_id = -1;
+ bool allow_6ghz = false;
int vht = wpa_s->conf->p2p_go_vht;
int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
int he = wpa_s->conf->p2p_go_he;
@@ -6869,6 +6884,8 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
edmg = 1;
} else if (os_strcmp(token, "persistent") == 0) {
persistent = 1;
+ } else if (os_strcmp(token, "allow_6ghz") == 0) {
+ allow_6ghz = true;
} else {
wpa_printf(MSG_DEBUG,
"CTRL: Invalid P2P_GROUP_ADD parameter: '%s'",
@@ -6905,10 +6922,10 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
return p2p_ctrl_group_add_persistent(wpa_s, group_id,
freq, freq2, ht40, vht,
max_oper_chwidth, he,
- edmg);
+ edmg, allow_6ghz);
return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
- max_oper_chwidth, he, edmg);
+ max_oper_chwidth, he, edmg, allow_6ghz);
}
@@ -10606,6 +10623,8 @@ static int wpas_ctrl_iface_pmksa_add(struct wpa_supplicant *wpa_s,
entry->network_ctx = ssid;
+ entry->external = true;
+
wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
entry = NULL;
ret = 0;
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index 7a6567330407..565ced0fd7e2 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -175,7 +175,7 @@ DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
}
if (wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types,
- req_dev_types, NULL, 0, 0, NULL, freq))
+ req_dev_types, NULL, 0, 0, NULL, freq, false))
reply = wpas_dbus_error_unknown_error(
message, "Could not start P2P find");
@@ -425,14 +425,15 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
goto inv_args;
if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
- 0, 0, 0, 0, NULL, 0, 0)) {
+ 0, 0, 0, 0, NULL, 0, 0,
+ false)) {
reply = wpas_dbus_error_unknown_error(
message,
"Failed to reinvoke a persistent group");
goto out;
}
} else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0, 0,
- 0, 0, 0))
+ 0, 0, 0, false))
goto inv_args;
out:
@@ -653,7 +654,7 @@ DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
persistent_group, 0, join, authorize_only,
go_intent, freq, 0, -1, 0, 0, 0, 0, 0, 0,
- NULL, 0);
+ NULL, 0, false);
if (new_pin >= 0) {
char npin[9];
@@ -810,7 +811,7 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
goto err;
if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0,
- 0, 0, 0) < 0) {
+ 0, 0, 0, false) < 0) {
reply = wpas_dbus_error_unknown_error(
message,
"Failed to reinvoke a persistent group");
@@ -821,7 +822,7 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
* No group ID means propose to a peer to join my active group
*/
if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname,
- peer_addr, NULL)) {
+ peer_addr, NULL, false)) {
reply = wpas_dbus_error_unknown_error(
message, "Failed to join to an active group");
goto out;
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index b511d1cc1457..a565e658f33d 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -4621,6 +4621,7 @@ static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_FILS
/* Update ERP next sequence number */
if (wpa_s->auth_alg == WPA_AUTH_ALG_FILS) {
+ fils_pmksa_cache_flush(wpa_s);
eapol_sm_update_erp_next_seq_num(
wpa_s->eapol,
data->assoc_reject.fils_erp_next_seq_num);
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index e3d3c1d71029..62c9a26a3490 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -347,9 +347,9 @@ static void wpas_p2p_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
params->only_new_results = 1;
}
- if (wpa_s->conf->p2p_6ghz_disable && !params->freqs) {
+ if (!params->p2p_include_6ghz && !params->freqs) {
wpa_printf(MSG_DEBUG,
- "P2P: 6 GHz disabled - update the scan frequency list");
+ "P2P: Exclude 6 GHz channels - update the scan frequency list");
wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, params,
0);
wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params,
@@ -394,7 +394,8 @@ static int wpas_p2p_search_social_channel(struct wpa_supplicant *wpa_s,
static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
unsigned int num_req_dev_types,
- const u8 *req_dev_types, const u8 *dev_id, u16 pw_id)
+ const u8 *req_dev_types, const u8 *dev_id, u16 pw_id,
+ bool include_6ghz)
{
struct wpa_supplicant *wpa_s = ctx;
struct wpa_driver_scan_params *params = NULL;
@@ -432,7 +433,8 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
num_req_dev_types, req_dev_types);
if (wps_ie == NULL)
goto fail;
-
+ if (!wpa_s->conf->p2p_6ghz_disable)
+ params->p2p_include_6ghz = include_6ghz;
switch (type) {
case P2P_SCAN_SOCIAL:
params->freqs = os_calloc(ARRAY_SIZE(social_channels_freq) + 1,
@@ -2063,6 +2065,14 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s,
}
ssid->auth_alg = WPA_AUTH_ALG_OPEN;
ssid->key_mgmt = WPA_KEY_MGMT_PSK;
+ if (is_6ghz_freq(ssid->frequency) &&
+ is_p2p_6ghz_capable(wpa_s->global->p2p)) {
+ ssid->auth_alg |= WPA_AUTH_ALG_SAE;
+ ssid->key_mgmt = WPA_KEY_MGMT_SAE;
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use SAE auth_alg and key_mgmt");
+ } else {
+ p2p_set_6ghz_dev_capab(wpa_s->global->p2p, false);
+ }
ssid->proto = WPA_PROTO_RSN;
ssid->pairwise_cipher = WPA_CIPHER_CCMP;
ssid->group_cipher = WPA_CIPHER_CCMP;
@@ -3234,7 +3244,7 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
wpa_s->conf->p2p_go_he,
wpa_s->conf->p2p_go_edmg, NULL,
go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0,
- 1);
+ 1, is_p2p_allow_6ghz(wpa_s->global->p2p));
} else if (bssid) {
wpa_s->user_initiated_pd = 0;
wpa_msg_global(wpa_s, MSG_INFO,
@@ -3463,7 +3473,8 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
channels,
ssid->mode == WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
- 0, 1);
+ 0, 1,
+ is_p2p_allow_6ghz(wpa_s->global->p2p));
}
@@ -3545,19 +3556,19 @@ static int wpas_p2p_default_channels(struct wpa_supplicant *wpa_s,
}
-static int has_channel(struct wpa_global *global,
- struct hostapd_hw_modes *mode, u8 chan, int *flags)
+static enum chan_allowed has_channel(struct wpa_global *global,
+ struct hostapd_hw_modes *mode, u8 op_class,
+ u8 chan, int *flags)
{
int i;
unsigned int freq;
- freq = (mode->mode == HOSTAPD_MODE_IEEE80211A ? 5000 : 2407) +
- chan * 5;
+ freq = ieee80211_chan_to_freq(NULL, op_class, chan);
if (wpas_p2p_disallowed_freq(global, freq))
return NOT_ALLOWED;
for (i = 0; i < mode->num_channels; i++) {
- if (mode->channels[i].chan == chan) {
+ if ((unsigned int) mode->channels[i].freq == freq) {
if (flags)
*flags = mode->channels[i].flag;
if (mode->channels[i].flag &
@@ -3576,15 +3587,15 @@ static int has_channel(struct wpa_global *global,
static int wpas_p2p_get_center_80mhz(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode,
- u8 channel)
+ u8 channel, const u8 *center_channels,
+ size_t num_chan)
{
- u8 center_channels[] = { 42, 58, 106, 122, 138, 155, 171 };
size_t i;
if (mode->mode != HOSTAPD_MODE_IEEE80211A)
return 0;
- for (i = 0; i < ARRAY_SIZE(center_channels); i++)
+ for (i = 0; i < num_chan; i++)
/*
* In 80 MHz, the bandwidth "spans" 12 channels (e.g., 36-48),
* so the center channel is 6 channels away from the start/end.
@@ -3597,25 +3608,43 @@ static int wpas_p2p_get_center_80mhz(struct wpa_supplicant *wpa_s,
}
+static const u8 center_channels_5ghz_80mhz[] = { 42, 58, 106, 122, 138,
+ 155, 171 };
+static const u8 center_channels_6ghz_80mhz[] = { 7, 23, 39, 55, 71, 87, 103,
+ 119, 135, 151, 167, 183, 199,
+ 215 };
+
static enum chan_allowed wpas_p2p_verify_80mhz(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode,
- u8 channel, u8 bw)
+ u8 op_class, u8 channel, u8 bw)
{
u8 center_chan;
int i, flags;
enum chan_allowed res, ret = ALLOWED;
+ const u8 *chans;
+ size_t num_chans;
+ bool is_6ghz = is_6ghz_op_class(op_class);
- center_chan = wpas_p2p_get_center_80mhz(wpa_s, mode, channel);
+ if (is_6ghz) {
+ chans = center_channels_6ghz_80mhz;
+ num_chans = ARRAY_SIZE(center_channels_6ghz_80mhz);
+ } else {
+ chans = center_channels_5ghz_80mhz;
+ num_chans = ARRAY_SIZE(center_channels_5ghz_80mhz);
+ }
+ center_chan = wpas_p2p_get_center_80mhz(wpa_s, mode, channel,
+ chans, num_chans);
if (!center_chan)
return NOT_ALLOWED;
- if (center_chan >= 58 && center_chan <= 138)
+ if (!is_6ghz && center_chan >= 58 && center_chan <= 138)
return NOT_ALLOWED; /* Do not allow DFS channels for P2P */
/* check all the channels are available */
for (i = 0; i < 4; i++) {
int adj_chan = center_chan - 6 + i * 4;
- res = has_channel(wpa_s->global, mode, adj_chan, &flags);
+ res = has_channel(wpa_s->global, mode, op_class, adj_chan,
+ &flags);
if (res == NOT_ALLOWED)
return NOT_ALLOWED;
if (res == NO_IR)
@@ -3637,15 +3666,15 @@ static enum chan_allowed wpas_p2p_verify_80mhz(struct wpa_supplicant *wpa_s,
static int wpas_p2p_get_center_160mhz(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode,
- u8 channel)
+ u8 channel, const u8 *center_channels,
+ size_t num_chan)
{
- u8 center_channels[] = { 50, 114, 163 };
unsigned int i;
if (mode->mode != HOSTAPD_MODE_IEEE80211A)
return 0;
- for (i = 0; i < ARRAY_SIZE(center_channels); i++)
+ for (i = 0; i < num_chan; i++)
/*
* In 160 MHz, the bandwidth "spans" 28 channels (e.g., 36-64),
* so the center channel is 14 channels away from the start/end.
@@ -3658,15 +3687,29 @@ static int wpas_p2p_get_center_160mhz(struct wpa_supplicant *wpa_s,
}
+static const u8 center_channels_5ghz_160mhz[] = { 50, 114, 163 };
+static const u8 center_channels_6ghz_160mhz[] = { 15, 47, 79, 111, 143, 175,
+ 207 };
+
static enum chan_allowed wpas_p2p_verify_160mhz(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode,
- u8 channel, u8 bw)
+ u8 op_class, u8 channel, u8 bw)
{
u8 center_chan;
int i, flags;
enum chan_allowed res, ret = ALLOWED;
+ const u8 *chans;
+ size_t num_chans;
- center_chan = wpas_p2p_get_center_160mhz(wpa_s, mode, channel);
+ if (is_6ghz_op_class(op_class)) {
+ chans = center_channels_6ghz_160mhz;
+ num_chans = ARRAY_SIZE(center_channels_6ghz_160mhz);
+ } else {
+ chans = center_channels_5ghz_160mhz;
+ num_chans = ARRAY_SIZE(center_channels_5ghz_160mhz);
+ }
+ center_chan = wpas_p2p_get_center_160mhz(wpa_s, mode, channel,
+ chans, num_chans);
if (!center_chan)
return NOT_ALLOWED;
/* VHT 160 MHz uses DFS channels in most countries. */
@@ -3675,7 +3718,8 @@ static enum chan_allowed wpas_p2p_verify_160mhz(struct wpa_supplicant *wpa_s,
for (i = 0; i < 8; i++) {
int adj_chan = center_chan - 14 + i * 4;
- res = has_channel(wpa_s->global, mode, adj_chan, &flags);
+ res = has_channel(wpa_s->global, mode, op_class, adj_chan,
+ &flags);
if (res == NOT_ALLOWED)
return NOT_ALLOWED;
@@ -3720,24 +3764,28 @@ static enum chan_allowed wpas_p2p_verify_edmg(struct wpa_supplicant *wpa_s,
static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode,
- u8 channel, u8 bw)
+ u8 op_class, u8 channel, u8 bw)
{
int flag = 0;
enum chan_allowed res, res2;
- res2 = res = has_channel(wpa_s->global, mode, channel, &flag);
+ res2 = res = has_channel(wpa_s->global, mode, op_class, channel, &flag);
if (bw == BW40MINUS) {
if (!(flag & HOSTAPD_CHAN_HT40MINUS))
return NOT_ALLOWED;
- res2 = has_channel(wpa_s->global, mode, channel - 4, NULL);
+ res2 = has_channel(wpa_s->global, mode, op_class, channel - 4,
+ NULL);
} else if (bw == BW40PLUS) {
if (!(flag & HOSTAPD_CHAN_HT40PLUS))
return NOT_ALLOWED;
- res2 = has_channel(wpa_s->global, mode, channel + 4, NULL);
+ res2 = has_channel(wpa_s->global, mode, op_class, channel + 4,
+ NULL);
} else if (bw == BW80) {
- res2 = wpas_p2p_verify_80mhz(wpa_s, mode, channel, bw);
+ res2 = wpas_p2p_verify_80mhz(wpa_s, mode, op_class, channel,
+ bw);
} else if (bw == BW160) {
- res2 = wpas_p2p_verify_160mhz(wpa_s, mode, channel, bw);
+ res2 = wpas_p2p_verify_160mhz(wpa_s, mode, op_class, channel,
+ bw);
} else if (bw == BW4320 || bw == BW6480 || bw == BW8640) {
return wpas_p2p_verify_edmg(wpa_s, mode, channel);
}
@@ -3791,7 +3839,8 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s,
ch < 149 && ch + o->inc > 149)
ch = 149;
- res = wpas_p2p_verify_channel(wpa_s, mode, ch, o->bw);
+ res = wpas_p2p_verify_channel(wpa_s, mode, o->op_class,
+ ch, o->bw);
if (res == ALLOWED) {
if (reg == NULL) {
if (cla == P2P_MAX_REG_CLASSES)
@@ -3861,7 +3910,8 @@ int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s,
(o->bw != BW40PLUS && o->bw != BW40MINUS) ||
ch != channel)
continue;
- ret = wpas_p2p_verify_channel(wpa_s, mode, ch, o->bw);
+ ret = wpas_p2p_verify_channel(wpa_s, mode, o->op_class,
+ ch, o->bw);
if (ret == ALLOWED)
return (o->bw == BW40MINUS) ? -1 : 1;
}
@@ -3871,21 +3921,45 @@ int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s,
int wpas_p2p_get_vht80_center(struct wpa_supplicant *wpa_s,
- struct hostapd_hw_modes *mode, u8 channel)
+ struct hostapd_hw_modes *mode, u8 channel,
+ u8 op_class)
{
- if (!wpas_p2p_verify_channel(wpa_s, mode, channel, BW80))
+ const u8 *chans;
+ size_t num_chans;
+
+ if (!wpas_p2p_verify_channel(wpa_s, mode, op_class, channel, BW80))
return 0;
- return wpas_p2p_get_center_80mhz(wpa_s, mode, channel);
+ if (is_6ghz_op_class(op_class)) {
+ chans = center_channels_6ghz_80mhz;
+ num_chans = ARRAY_SIZE(center_channels_6ghz_80mhz);
+ } else {
+ chans = center_channels_5ghz_80mhz;
+ num_chans = ARRAY_SIZE(center_channels_5ghz_80mhz);
+ }
+ return wpas_p2p_get_center_80mhz(wpa_s, mode, channel,
+ chans, num_chans);
}
int wpas_p2p_get_vht160_center(struct wpa_supplicant *wpa_s,
- struct hostapd_hw_modes *mode, u8 channel)
+ struct hostapd_hw_modes *mode, u8 channel,
+ u8 op_class)
{
- if (!wpas_p2p_verify_channel(wpa_s, mode, channel, BW160))
+ const u8 *chans;
+ size_t num_chans;
+
+ if (!wpas_p2p_verify_channel(wpa_s, mode, op_class, channel, BW160))
return 0;
- return wpas_p2p_get_center_160mhz(wpa_s, mode, channel);
+ if (is_6ghz_op_class(op_class)) {
+ chans = center_channels_6ghz_160mhz;
+ num_chans = ARRAY_SIZE(center_channels_6ghz_160mhz);
+ } else {
+ chans = center_channels_5ghz_160mhz;
+ num_chans = ARRAY_SIZE(center_channels_5ghz_160mhz);
+ }
+ return wpas_p2p_get_center_160mhz(wpa_s, mode, channel,
+ chans, num_chans);
}
@@ -4425,10 +4499,10 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
persistent_go->mode ==
WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
- 0, 0);
+ 0, 0, false);
} else if (response_done) {
wpas_p2p_group_add(wpa_s, 1, freq,
- 0, 0, 0, 0, 0, 0);
+ 0, 0, 0, 0, 0, 0, false);
}
if (passwd_id == DEV_PW_P2PS_DEFAULT) {
@@ -4547,9 +4621,11 @@ static int wpas_prov_disc_resp_cb(void *ctx)
wpa_s, persistent_go, 0, 0, 0, 0, 0, 0, 0, 0, 0,
NULL,
persistent_go->mode == WPAS_MODE_P2P_GO ?
- P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0);
+ P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0,
+ is_p2p_allow_6ghz(wpa_s->global->p2p));
} else {
- wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0, 0, 0);
+ wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0, 0, 0,
+ is_p2p_allow_6ghz(wpa_s->global->p2p));
}
return 1;
@@ -5157,7 +5233,8 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
wpa_s->p2p_go_max_oper_chwidth,
wpa_s->p2p_go_he,
wpa_s->p2p_go_edmg,
- NULL, 0);
+ NULL, 0,
+ is_p2p_allow_6ghz(wpa_s->global->p2p));
return;
}
@@ -5355,7 +5432,8 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
if (freq > 0) {
freqs[0] = freq;
params.freqs = freqs;
- } else if (wpa_s->conf->p2p_6ghz_disable) {
+ } else if (wpa_s->conf->p2p_6ghz_disable ||
+ !is_p2p_allow_6ghz(wpa_s->global->p2p)) {
wpa_printf(MSG_DEBUG,
"P2P: 6 GHz disabled - update the scan frequency list");
wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, &params,
@@ -5392,7 +5470,7 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
* the new scan results become available.
*/
ret = wpa_drv_scan(wpa_s, &params);
- if (wpa_s->conf->p2p_6ghz_disable && params.freqs != freqs)
+ if (params.freqs != freqs)
os_free(params.freqs);
if (!ret) {
os_get_reltime(&wpa_s->scan_trigger_time);
@@ -5622,6 +5700,10 @@ static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
res = wpa_drv_get_pref_freq_list(wpa_s, iface_type,
&max_pref_freq,
pref_freq_list);
+ if (!is_p2p_allow_6ghz(wpa_s->global->p2p))
+ max_pref_freq = p2p_remove_6ghz_channels(pref_freq_list,
+ max_pref_freq);
+
if (!res && max_pref_freq > 0) {
*num_pref_freq = max_pref_freq;
i = 0;
@@ -5681,6 +5763,40 @@ exit_free:
}
+static bool is_p2p_6ghz_supported(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr)
+{
+ if (wpa_s->conf->p2p_6ghz_disable ||
+ !get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
+ HOSTAPD_MODE_IEEE80211A, true))
+ return false;
+
+ if (!p2p_wfd_enabled(wpa_s->global->p2p))
+ return false;
+ if (peer_addr && !p2p_peer_wfd_enabled(wpa_s->global->p2p, peer_addr))
+ return false;
+
+ return true;
+}
+
+
+static int wpas_p2p_check_6ghz(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr, bool allow_6ghz, int freq)
+{
+ if (allow_6ghz && is_p2p_6ghz_supported(wpa_s, peer_addr)) {
+ wpa_printf(MSG_DEBUG,
+ "P2P: Allow connection on 6 GHz channels");
+ p2p_set_6ghz_dev_capab(wpa_s->global->p2p, true);
+ } else {
+ if (is_6ghz_freq(freq))
+ return -2;
+ p2p_set_6ghz_dev_capab(wpa_s->global->p2p, false);
+ }
+
+ return 0;
+}
+
+
/**
* wpas_p2p_connect - Request P2P Group Formation to be started
* @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
@@ -5705,6 +5821,7 @@ exit_free:
* (CHANWIDTH_*).
* @group_ssid: Specific Group SSID for join or %NULL if not set
* @group_ssid_len: Length of @group_ssid in octets
+ * @allow_6ghz: Allow P2P connection on 6 GHz channels
* Returns: 0 or new PIN (if pin was %NULL) on success, -1 on unspecified
* failure, -2 on failure due to channel not currently available,
* -3 if forced channel is not supported
@@ -5715,7 +5832,8 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
int go_intent, int freq, unsigned int vht_center_freq2,
int persistent_id, int pd, int ht40, int vht,
unsigned int vht_chwidth, int he, int edmg,
- const u8 *group_ssid, size_t group_ssid_len)
+ const u8 *group_ssid, size_t group_ssid_len,
+ bool allow_6ghz)
{
int force_freq = 0, pref_freq = 0;
int ret = 0, res;
@@ -5734,7 +5852,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
return -1;
}
- if (is_6ghz_freq(freq) && wpa_s->conf->p2p_6ghz_disable)
+ if (wpas_p2p_check_6ghz(wpa_s, peer_addr, allow_6ghz, freq))
return -2;
os_free(wpa_s->global->add_psk);
@@ -6012,6 +6130,9 @@ static int wpas_p2p_select_go_freq(struct wpa_supplicant *wpa_s, int freq)
res = wpa_drv_get_pref_freq_list(wpa_s, WPA_IF_P2P_GO,
&size, pref_freq_list);
+ if (!is_p2p_allow_6ghz(wpa_s->global->p2p))
+ size = p2p_remove_6ghz_channels(pref_freq_list, size);
+
if (!res && size > 0) {
i = 0;
while (i < size &&
@@ -6439,14 +6560,16 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
enum hostapd_hw_mode mode;
struct hostapd_hw_modes *hwmode;
u8 chan;
+ u8 op_class;
cand = wpa_s->p2p_group_common_freqs[i];
+ op_class = is_6ghz_freq(cand) ? 133 : 128;
mode = ieee80211_freq_to_chan(cand, &chan);
hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
mode, is_6ghz_freq(cand));
if (!hwmode ||
- wpas_p2p_verify_channel(wpa_s, hwmode, chan,
- BW80) != ALLOWED)
+ wpas_p2p_verify_channel(wpa_s, hwmode, op_class,
+ chan, BW80) != ALLOWED)
continue;
if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
params->freq = cand;
@@ -6465,20 +6588,44 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
enum hostapd_hw_mode mode;
struct hostapd_hw_modes *hwmode;
- u8 chan;
+ u8 chan, op_class;
+ bool is_6ghz, supported = false;
+ is_6ghz = is_6ghz_freq(cand);
cand = wpa_s->p2p_group_common_freqs[i];
mode = ieee80211_freq_to_chan(cand, &chan);
hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
- mode, is_6ghz_freq(cand));
+ mode, is_6ghz);
if (!wpas_same_band(wpa_s->current_ssid->frequency,
cand) ||
- !hwmode ||
- (wpas_p2p_verify_channel(wpa_s, hwmode, chan,
- BW40MINUS) != ALLOWED &&
- wpas_p2p_verify_channel(wpa_s, hwmode, chan,
- BW40PLUS) != ALLOWED))
+ !hwmode)
+ continue;
+ if (is_6ghz &&
+ wpas_p2p_verify_channel(wpa_s, hwmode, 132, chan,
+ BW40) == ALLOWED)
+ supported = true;
+
+ if (!is_6ghz &&
+ ieee80211_freq_to_channel_ext(
+ cand, -1, CHANWIDTH_USE_HT, &op_class,
+ &chan) != NUM_HOSTAPD_MODES &&
+ wpas_p2p_verify_channel(
+ wpa_s, hwmode, op_class, chan,
+ BW40MINUS) == ALLOWED)
+ supported = true;
+
+ if (!supported && !is_6ghz &&
+ ieee80211_freq_to_channel_ext(
+ cand, 1, CHANWIDTH_USE_HT, &op_class,
+ &chan) != NUM_HOSTAPD_MODES &&
+ wpas_p2p_verify_channel(
+ wpa_s, hwmode, op_class, chan,
+ BW40PLUS) == ALLOWED)
+ supported = true;
+
+ if (!supported)
continue;
+
if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
params->freq = cand;
wpa_printf(MSG_DEBUG,
@@ -6599,6 +6746,7 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
* @vht: Start GO with VHT support
* @vht_chwidth: channel bandwidth for GO operating with VHT support
* @edmg: Start GO with EDMG support
+ * @allow_6ghz: Allow P2P group creation on a 6 GHz channel
* Returns: 0 on success, -1 on failure
*
* This function creates a new P2P group with the local end as the Group Owner,
@@ -6606,12 +6754,15 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
*/
int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
int freq, int vht_center_freq2, int ht40, int vht,
- int max_oper_chwidth, int he, int edmg)
+ int max_oper_chwidth, int he, int edmg,
+ bool allow_6ghz)
{
struct p2p_go_neg_results params;
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
+ if (wpas_p2p_check_6ghz(wpa_s, NULL, allow_6ghz, freq))
+ return -1;
os_free(wpa_s->global->add_psk);
wpa_s->global->add_psk = NULL;
@@ -6710,7 +6861,8 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
int vht, int max_oper_chwidth, int he,
int edmg,
const struct p2p_channels *channels,
- int connection_timeout, int force_scan)
+ int connection_timeout, int force_scan,
+ bool allow_6ghz)
{
struct p2p_go_neg_results params;
int go = 0, freq;
@@ -7102,7 +7254,8 @@ int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout,
enum p2p_discovery_type type,
unsigned int num_req_dev_types, const u8 *req_dev_types,
const u8 *dev_id, unsigned int search_delay,
- u8 seek_cnt, const char **seek_string, int freq)
+ u8 seek_cnt, const char **seek_string, int freq,
+ bool include_6ghz)
{
wpas_p2p_clear_pending_action_tx(wpa_s);
wpa_s->global->p2p_long_listen = 0;
@@ -7121,7 +7274,8 @@ int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout,
return p2p_find(wpa_s->global->p2p, timeout, type,
num_req_dev_types, req_dev_types, dev_id,
- search_delay, seek_cnt, seek_string, freq);
+ search_delay, seek_cnt, seek_string, freq,
+ include_6ghz);
}
@@ -7337,7 +7491,7 @@ int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr)
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
int vht_center_freq2, int ht40, int vht, int max_chwidth,
- int pref_freq, int he, int edmg)
+ int pref_freq, int he, int edmg, bool allow_6ghz)
{
enum p2p_invite_role role;
u8 *bssid = NULL;
@@ -7346,6 +7500,9 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
int no_pref_freq_given = pref_freq == 0;
unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS], size;
+ if (wpas_p2p_check_6ghz(wpa_s, NULL, allow_6ghz, freq))
+ return -1;
+
wpa_s->global->p2p_invite_group = NULL;
if (peer_addr)
os_memcpy(wpa_s->p2p_auth_invite, peer_addr, ETH_ALEN);
@@ -7420,7 +7577,8 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
/* Invite to join an active group */
int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
- const u8 *peer_addr, const u8 *go_dev_addr)
+ const u8 *peer_addr, const u8 *go_dev_addr,
+ bool allow_6ghz)
{
struct wpa_global *global = wpa_s->global;
enum p2p_invite_role role;
@@ -7483,6 +7641,8 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
+ if (wpas_p2p_check_6ghz(wpa_s, peer_addr, allow_6ghz, freq))
+ return -1;
size = P2P_MAX_PREF_CHANNELS;
res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq,
@@ -8385,7 +8545,7 @@ static int wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
wpa_s->p2p_go_max_oper_chwidth,
wpa_s->p2p_go_he,
wpa_s->p2p_go_edmg,
- NULL, 0);
+ NULL, 0, is_p2p_allow_6ghz(wpa_s->global->p2p));
return ret;
}
@@ -8923,7 +9083,7 @@ static int wpas_p2p_nfc_join_group(struct wpa_supplicant *wpa_s,
-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
wpa_s->p2p_go_he, wpa_s->p2p_go_edmg,
params->go_ssid_len ? params->go_ssid : NULL,
- params->go_ssid_len);
+ params->go_ssid_len, false);
}
@@ -9002,7 +9162,7 @@ static int wpas_p2p_nfc_init_go_neg(struct wpa_supplicant *wpa_s,
forced_freq, wpa_s->p2p_go_vht_center_freq2,
-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
wpa_s->p2p_go_he, wpa_s->p2p_go_edmg,
- NULL, 0);
+ NULL, 0, false);
}
@@ -9019,7 +9179,7 @@ static int wpas_p2p_nfc_resp_go_neg(struct wpa_supplicant *wpa_s,
forced_freq, wpa_s->p2p_go_vht_center_freq2,
-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
wpa_s->p2p_go_he, wpa_s->p2p_go_edmg,
- NULL, 0);
+ NULL, 0, false);
if (res)
return res;
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 941198e3afb0..dee9c1bcc1e1 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -38,19 +38,21 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
int go_intent, int freq, unsigned int vht_center_freq2,
int persistent_id, int pd, int ht40, int vht,
unsigned int vht_chwidth, int he, int edmg,
- const u8 *group_ssid, size_t group_ssid_len);
+ const u8 *group_ssid, size_t group_ssid_len,
+ bool allow_6ghz);
int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s,
int freq, struct wpa_ssid *ssid);
int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
int freq, int vht_center_freq2, int ht40, int vht,
- int max_oper_chwidth, int he, int edmg);
+ int max_oper_chwidth, int he, int edmg, bool allow_6ghz);
int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int addr_allocated,
int force_freq, int neg_freq,
int vht_center_freq2, int ht40, int vht,
int max_oper_chwidth, int he, int edmg,
const struct p2p_channels *channels,
- int connection_timeout, int force_scan);
+ int connection_timeout, int force_scan,
+ bool allow_6ghz);
struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
enum wpas_p2p_prov_disc_use {
@@ -73,7 +75,8 @@ int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout,
enum p2p_discovery_type type,
unsigned int num_req_dev_types, const u8 *req_dev_types,
const u8 *dev_id, unsigned int search_delay,
- u8 seek_cnt, const char **seek_string, int freq);
+ u8 seek_cnt, const char **seek_string, int freq,
+ bool include_6ghz);
void wpas_p2p_stop_find(struct wpa_supplicant *wpa_s);
int wpas_p2p_listen(struct wpa_supplicant *wpa_s, unsigned int timeout);
int wpas_p2p_listen_start(struct wpa_supplicant *wpa_s, unsigned int timeout);
@@ -117,9 +120,10 @@ int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr);
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
int vht_center_freq2, int ht40, int vht, int max_chwidth,
- int pref_freq, int he, int edmg);
+ int pref_freq, int he, int edmg, bool allow_6ghz);
int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
- const u8 *peer_addr, const u8 *go_dev_addr);
+ const u8 *peer_addr, const u8 *go_dev_addr,
+ bool allow_6ghz);
int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1,
u32 interval1, u32 duration2, u32 interval2);
int wpas_p2p_ext_listen(struct wpa_supplicant *wpa_s, unsigned int period,
@@ -145,9 +149,11 @@ int wpas_p2p_scan_no_go_seen(struct wpa_supplicant *wpa_s);
int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode, u8 channel);
int wpas_p2p_get_vht80_center(struct wpa_supplicant *wpa_s,
- struct hostapd_hw_modes *mode, u8 channel);
+ struct hostapd_hw_modes *mode, u8 channel,
+ u8 op_class);
int wpas_p2p_get_vht160_center(struct wpa_supplicant *wpa_s,
- struct hostapd_hw_modes *mode, u8 channel);
+ struct hostapd_hw_modes *mode, u8 channel,
+ u8 op_class);
unsigned int wpas_p2p_search_delay(struct wpa_supplicant *wpa_s);
void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr,
const u8 *p2p_dev_addr,
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index c194806cd7f2..97a8d9a638d6 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -2850,6 +2850,7 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src)
params->relative_rssi = src->relative_rssi;
params->relative_adjust_band = src->relative_adjust_band;
params->relative_adjust_rssi = src->relative_adjust_rssi;
+ params->p2p_include_6ghz = src->p2p_include_6ghz;
return params;
failed:
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 72aa9b5b8f18..f2c42ff354e7 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -1340,8 +1340,15 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
if (status_code != WLAN_STATUS_SUCCESS &&
status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT &&
- status_code != WLAN_STATUS_SAE_PK)
+ status_code != WLAN_STATUS_SAE_PK) {
+ const u8 *bssid = sa ? sa : wpa_s->pending_bssid;
+
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR
+ " auth_type=%u auth_transaction=%u status_code=%u",
+ MAC2STR(bssid), WLAN_AUTH_SAE,
+ auth_transaction, status_code);
return -1;
+ }
if (auth_transaction == 1) {
u16 res;
@@ -1542,7 +1549,7 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
int res;
res = sme_sae_auth(wpa_s, data->auth.auth_transaction,
data->auth.status_code, data->auth.ies,
- data->auth.ies_len, 0, NULL);
+ data->auth.ies_len, 0, data->auth.peer);
if (res < 0) {
wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index c4c6651d42e6..8a1a44690ba5 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -1343,11 +1343,11 @@ static int wnm_fetch_scan_results(struct wpa_supplicant *wpa_s)
continue;
bss = wpa_s->current_bss;
ssid_ie = wpa_scan_get_ie(res, WLAN_EID_SSID);
- if (bss && ssid_ie &&
+ if (bss && ssid_ie && ssid_ie[1] &&
(bss->ssid_len != ssid_ie[1] ||
os_memcmp(bss->ssid, ssid_ie + 2,
bss->ssid_len) != 0))
- continue;
+ continue; /* Skip entries for other ESSs */
/* Potential candidate found */
found = 1;
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 0d9b9caa5906..cc184dba5feb 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -7537,6 +7537,46 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
#ifdef CONFIG_FILS
+
+void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+ const u8 *realm, *username, *rrk;
+ size_t realm_len, username_len, rrk_len;
+ u16 next_seq_num;
+
+ /* Clear the PMKSA cache entry if FILS authentication was rejected.
+ * Check for ERP keys existing to limit when this can be done since
+ * the rejection response is not protected and such triggers should
+ * really not allow internal state to be modified unless required to
+ * avoid significant issues in functionality. In addition, drop
+ * externally configure PMKSA entries even without ERP keys since it
+ * is possible for an external component to add PMKSA entries for FILS
+ * authentication without restoring previously generated ERP keys.
+ *
+ * In this case, this is needed to allow recovery from cases where the
+ * AP or authentication server has dropped PMKSAs and ERP keys. */
+ if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
+ return;
+
+ if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
+ &username, &username_len,
+ &realm, &realm_len, &next_seq_num,
+ &rrk, &rrk_len) != 0 ||
+ !realm) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "FILS: Drop external PMKSA cache entry");
+ wpa_sm_aborted_external_cached(wpa_s->wpa);
+ wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
+ return;
+ }
+
+ wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
+ wpa_sm_aborted_cached(wpa_s->wpa);
+ wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
+}
+
+
void fils_connection_failure(struct wpa_supplicant *wpa_s)
{
struct wpa_ssid *ssid = wpa_s->current_ssid;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 6877f5a9960d..60acb53c5c38 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1501,6 +1501,7 @@ void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s);
void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s);
void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid);
void fils_connection_failure(struct wpa_supplicant *wpa_s);
+void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s);
int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s);
int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s);
void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason);
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index 029349b08d20..5633f3d1ecaf 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -372,6 +372,7 @@ static int wpa_supplicant_wps_cred(void *ctx,
#ifdef CONFIG_WPS_REG_DISABLE_OPEN
int registrar = 0;
#endif /* CONFIG_WPS_REG_DISABLE_OPEN */
+ bool add_sae;
if ((wpa_s->conf->wps_cred_processing == 1 ||
wpa_s->conf->wps_cred_processing == 2) && cred->cred_attr) {
@@ -534,8 +535,12 @@ static int wpa_supplicant_wps_cred(void *ctx,
case WPS_AUTH_WPA2PSK:
ssid->auth_alg = WPA_AUTH_ALG_OPEN;
ssid->key_mgmt = WPA_KEY_MGMT_PSK;
- if (wpa_s->conf->wps_cred_add_sae &&
- cred->key_len != 2 * PMK_LEN) {
+ add_sae = wpa_s->conf->wps_cred_add_sae;
+#ifdef CONFIG_P2P
+ if (ssid->p2p_group && is_p2p_6ghz_capable(wpa_s->global->p2p))
+ add_sae = true;
+#endif /* CONFIG_P2P */
+ if (add_sae && cred->key_len != 2 * PMK_LEN) {
ssid->auth_alg = 0;
ssid->key_mgmt |= WPA_KEY_MGMT_SAE;
ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;