Revert "Revert "[wpa_supplicant] cumilative patch from commit 3a..."
Revert submission 28102966-revert-26533062-Supplicant_merge_June24-CUATTSRBBR
Reason for revert: Fixed the regression issue (ag/28389573)
Reverted changes: /q/submissionid:28102966-revert-26533062-Supplicant_merge_June24-CUATTSRBBR
Bug: 329004037
Test: Turn ON/OFF SoftAp multiple times
Change-Id: Ibfff2a847be5678f1a6d77e28506a05936812a91
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index eb4224b..baf3ad1 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -139,11 +139,7 @@
OBJS += src/utils/bitfield.c
OBJS += src/utils/ip_addr.c
OBJS += src/utils/crc32.c
-OBJS += wmm_ac.c
-OBJS += op_classes.c
-OBJS += rrm.c
OBJS += twt.c
-OBJS += robust_av.c
OBJS_p = wpa_passphrase.c
OBJS_p += src/utils/common.c
OBJS_p += src/utils/wpa_debug.c
@@ -324,6 +320,12 @@
endif
endif
+ifdef CONFIG_NAN_USD
+OBJS += src/common/nan_de.c
+OBJS += nan_usd.c
+L_CFLAGS += -DCONFIG_NAN_USD
+endif
+
ifdef CONFIG_OWE
L_CFLAGS += -DCONFIG_OWE
NEED_ECC=y
@@ -352,6 +354,10 @@
CONFIG_WNM=y
endif
+ifdef CONFIG_BGSCAN_SIMPLE
+CONFIG_WNM=y
+endif
+
ifdef CONFIG_WNM
L_CFLAGS += -DCONFIG_WNM
OBJS += wnm_sta.c
@@ -466,6 +472,28 @@
L_CFLAGS += -DCONFIG_NO_TKIP
endif
+ifdef CONFIG_NO_RRM
+L_CFLAGS += -DCONFIG_NO_RRM
+else
+OBJS += rrm.c
+ifdef CONFIG_AP
+OBJS += src/ap/rrm.c
+endif
+OBJS += op_classes.c
+endif
+
+ifdef CONFIG_NO_WMM_AC
+L_CFLAGS += -DCONFIG_NO_WMM_AC
+else
+OBJS += wmm_ac.c
+endif
+
+ifdef CONFIG_NO_ROBUST_AV
+L_CFLAGS += -DCONFIG_NO_ROBUST_AV
+else
+OBJS += robust_av.c
+endif
+
include $(LOCAL_PATH)/src/drivers/drivers.mk
@@ -949,7 +977,6 @@
OBJS += src/ap/bss_load.c
OBJS += src/ap/eap_user_db.c
OBJS += src/ap/neighbor_db.c
-OBJS += src/ap/rrm.c
OBJS += src/ap/ieee802_11_ht.c
ifdef CONFIG_IEEE80211AC
OBJS += src/ap/ieee802_11_vht.c
@@ -1010,6 +1037,9 @@
OBJS += src/ap/gas_query_ap.c
NEED_AP_GAS_SERV=y
endif
+ifdef CONFIG_NAN_USD
+OBJS += src/ap/nan_usd_ap.c
+endif
ifdef CONFIG_INTERWORKING
NEED_AP_GAS_SERV=y
endif
@@ -1028,6 +1058,7 @@
ifdef CONFIG_TESTING_OPTIONS
L_CFLAGS += -DCONFIG_TESTING_OPTIONS
+NEED_AES_WRAP=y
endif
ifdef NEED_RSN_AUTHENTICATOR
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 8c417b8..93fc338 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -64,6 +64,7 @@
CFLAGS += -DCONFIG_TESTING_OPTIONS
CONFIG_WPS_TESTING=y
CONFIG_TDLS_TESTING=y
+NEED_AES_WRAP=y
endif
mkconfig:
@@ -111,10 +112,7 @@
OBJS += ../src/utils/bitfield.o
OBJS += ../src/utils/ip_addr.o
OBJS += ../src/utils/crc32.o
-OBJS += op_classes.o
-OBJS += rrm.o
OBJS += twt.o
-OBJS += robust_av.o
OBJS_p = wpa_passphrase.o
OBJS_p += ../src/utils/common.o
OBJS_p += ../src/utils/wpa_debug.o
@@ -123,7 +121,6 @@
OBJS_c += ../src/utils/wpa_debug.o
OBJS_c += ../src/utils/common.o
OBJS_c += ../src/common/cli.o
-OBJS += wmm_ac.o
ifndef CONFIG_OS
ifdef CONFIG_NATIVE_WINDOWS
@@ -192,7 +189,7 @@
endif
ifdef CONFIG_CODE_COVERAGE
-CFLAGS += -O0 -fprofile-arcs -ftest-coverage
+CFLAGS += -O0 -fprofile-arcs -ftest-coverage -U_FORTIFY_SOURCE
LIBS += -lgcov
LIBS_c += -lgcov
LIBS_p += -lgcov
@@ -318,6 +315,12 @@
endif
endif
+ifdef CONFIG_NAN_USD
+OBJS += ../src/common/nan_de.o
+OBJS += nan_usd.o
+CFLAGS += -DCONFIG_NAN_USD
+endif
+
ifdef CONFIG_OWE
CFLAGS += -DCONFIG_OWE
NEED_ECC=y
@@ -346,6 +349,10 @@
CONFIG_WNM=y
endif
+ifdef CONFIG_BGSCAN_SIMPLE
+CONFIG_WNM=y
+endif
+
ifdef CONFIG_WNM
CFLAGS += -DCONFIG_WNM
OBJS += wnm_sta.o
@@ -477,6 +484,28 @@
CFLAGS += -DCONFIG_NO_LOAD_DYNAMIC_EAP
endif
+ifdef CONFIG_NO_RRM
+CFLAGS += -DCONFIG_NO_RRM
+else
+OBJS += rrm.o
+ifdef CONFIG_AP
+OBJS += ../src/ap/rrm.o
+endif
+OBJS += op_classes.o
+endif
+
+ifdef CONFIG_NO_WMM_AC
+CFLAGS += -DCONFIG_NO_WMM_AC
+else
+OBJS += wmm_ac.o
+endif
+
+ifdef CONFIG_NO_ROBUST_AV
+CFLAGS += -DCONFIG_NO_ROBUST_AV
+else
+OBJS += robust_av.o
+endif
+
include ../src/drivers/drivers.mak
ifdef CONFIG_AP
OBJS_d += $(DRV_BOTH_OBJS)
@@ -983,7 +1012,6 @@
OBJS += ../src/ap/bss_load.o
OBJS += ../src/ap/eap_user_db.o
OBJS += ../src/ap/neighbor_db.o
-OBJS += ../src/ap/rrm.o
OBJS += ../src/ap/ieee802_11_ht.o
ifdef CONFIG_IEEE80211AC
OBJS += ../src/ap/ieee802_11_vht.o
@@ -1044,6 +1072,9 @@
OBJS += ../src/ap/gas_query_ap.o
NEED_AP_GAS_SERV=y
endif
+ifdef CONFIG_NAN_USD
+OBJS += ../src/ap/nan_usd_ap.o
+endif
ifdef CONFIG_INTERWORKING
NEED_AP_GAS_SERV=y
endif
@@ -1058,6 +1089,7 @@
ifdef CONFIG_MBO
OBJS += mbo.o
CFLAGS += -DCONFIG_MBO
+NEED_GAS=y
endif
ifdef NEED_RSN_AUTHENTICATOR
@@ -1076,17 +1108,20 @@
ifdef CONFIG_PCSC
# PC/SC interface for smartcards (USIM, GSM SIM)
-CFLAGS += -DPCSC_FUNCS -I/usr/include/PCSC
+CFLAGS += -DPCSC_FUNCS
OBJS += ../src/utils/pcsc_funcs.o
ifdef CONFIG_NATIVE_WINDOWS
#Once MinGW gets support for WinScard, -lwinscard could be used instead of the
#dynamic symbol loading that is now used in pcsc_funcs.c
#LIBS += -lwinscard
+CFLAGS += -I/usr/include/PCSC
else
ifdef CONFIG_OSX
LIBS += -framework PCSC
+CFLAGS += -I/usr/include/PCSC
else
LIBS += $(shell $(PKG_CONFIG) --libs libpcsclite)
+CFLAGS += $(shell $(PKG_CONFIG) --cflags libpcsclite)
endif
endif
endif
diff --git a/wpa_supplicant/README-NAN-USD b/wpa_supplicant/README-NAN-USD
new file mode 100644
index 0000000..5dfe6ee
--- /dev/null
+++ b/wpa_supplicant/README-NAN-USD
@@ -0,0 +1,147 @@
+Wi-Fi Aware unsynchronized service discovery (NAN USD)
+======================================================
+
+This document descibes how the unsynchronized service discovery defined
+in the Wi-Fi Aware specification v4.0 can be used with wpa_spplicant.
+
+More information about Wi-Fi Aware is available from this Wi-Fi
+Alliance web page:
+https://www.wi-fi.org/discover-wi-fi/wi-fi-aware
+
+Build config setup
+------------------
+
+The following parameters must be included in the config file used to
+compile hostapd and wpa_supplicant.
+
+wpa_supplicant build config
+---------------------------
+
+Enable NAN USD in wpa_supplicant build config file
+
+CONFIG_NAN_USD=y
+
+Control interface commands and events
+-------------------------------------
+
+Following control interface commands can be used:
+
+NAN_PUBLISH service_name=<name> [ttl=<time-to-live-in-sec>] [freq=<in MHz>] [freq_list=<comma separate list of MHz>] [srv_proto_type=<type>] [ssi=<service specific information (hexdump)>] [solicited=0] [unsolicited=0] [fsd=0]
+
+If ttl=0 or the parameter is not included, only one Publish message is
+transmitted.
+
+If freq is not included, the default frequency 2437 MHz (channel 6 on
+the 2.4 GHz band) is used.
+
+If freq_list is included, publisher iterates over all the listed
+channels. A special freq_list=all value can be used to generate the
+channel list automatically based on the list of allowed 2.4 and 5 GHz
+channels.
+
+srv_proto_type values are defined in the Service Protocol Types table in
+the Wi-Fi Aware specification.
+
+This command returns the assigned publish_id value or FAIL on failure.
+
+This command maps to the Publish() method in the NAN Discovery Engine.
+
+NAN_CANCEL_PUBLISH publish_id=<id from NAN_PUBLISH>
+
+This command maps to the CancelPublish() method in the NAN Discovery
+Engine.
+
+NAN_UPDATE_PUBLISH publish_id=<id from NAN_PUBLISH> [ssi=<service specific information (hexdump)>]
+
+This command maps to the UpdatePublish() method in the NAN Discovery
+Engine.
+
+NAN_SUBSCRIBE service_name=<name> [active=1] [ttl=<time-to-live-in-sec>] [freq=<in MHz>] [srv_proto_type=<type>] [ssi=<service specific information (hexdump)>]
+
+If ttl=0 or the parameter is not included, operation is terminated once
+the first matching publisher is found.
+
+If freq is not included, the default frequency 2437 MHz (channel 6 on
+the 2.4 GHz band) is used.
+
+srv_proto_type values are defined in the Service Protocol Types table in
+the Wi-Fi Aware specification.
+
+This command returns the assigned subscribe_id value or FAIL on failure.
+
+This command maps to the Subscribe() method in the NAN Discovery Engine.
+
+NAN_CANCEL_SUBSCRIBE subscribe_id=<id from NAN_SUBSCRIBE>
+
+This command maps to the CancelSubscribe() method in the NAN Discovery Engine.
+
+NAN_TRANSMIT handle=<id from NAN_PUBLISH or NAN_SUBSCRIBE> req_instance=<peer's id> address=<peer's MAC address> [ssi=<service specific information (hexdump)>]
+
+This command maps to the Transmit() method in the NAN Discovery Engine.
+
+Following control interface events are used:
+
+NAN-DISCOVERY-RESULT subscribe_id=<own id> publish_id=<peer's id> address=<peer MAC address> fsd=<0/1> fsd_gas=<0/1> srv_proto_type=<type> ssi=<service specific information (hexdump)>
+
+This event maps to the DiscoveryResult() event in the NAN Discovery
+Engine.
+
+NAN-REPLIED publish_id=<own id> address=<peer MAC address> subscribe_id=<peer id> srv_proto_type=<ype> ssi=<service specific information (hexdump)>
+
+This event maps to the Replied() event in the NAN Discovery Engine.
+
+NAN-PUBLISH-TERMINATED publish_id=<own id> reason=<timeout/user-request/failure>
+
+This event maps to the PublishTerminated() event in the NAN Discovery
+Engine.
+
+NAN-SUBSCRIBE-TERMINATED subscribe_id=<own id> reason=<timeout/user-request/failure>
+
+This event maps to the SubscribeTerminate() event in the NAN Discovery
+Engine.
+
+NAN-RECEIVE id=<own id> peer_instance_id=<peer id> address=<peer MAC adress> ssi=<service specific information (hexdump)>
+
+This event maps to the Receive() event in the NAN Discovery Engine.
+
+
+Example operation
+-----------------
+
+Start Subscribe and Publish functions:
+
+dev0: NAN_SUBSCRIBE service_name=_test srv_proto_type=3 ssi=1122334455
+--> returns 7
+
+dev1: NAN_PUBLISH service_name=_test srv_proto_type=3 ssi=6677
+--> returns 5
+
+Subscriber notification of a discovery:
+
+event on dev0: <3>NAN-DISCOVERY-RESULT subscribe_id=7 publish_id=5 address=02:00:00:00:01:00 fsd=1 fsd_gas=0 srv_proto_type=3 ssi=6677
+
+Publisher notification of a Follow-up message with no ssi (to enter
+paused state to continue exchange with the subscriber):
+
+event on dev1: <3>NAN-RECEIVE id=5 peer_instance_id=7 address=02:00:00:00:00:00 ssi=
+
+Subscriber sending a Follow-up message:
+
+dev0: NAN_TRANSMIT handle=7 req_instance_id=5 address=02:00:00:00:01:00 ssi=8899
+
+Publisher receiving the Follow-up message:
+
+event on dev1: <3>NAN-RECEIVE id=5 peer_instance_id=7 address=02:00:00:00:00:00 ssi=8899
+
+Publisher sending a Follow-up message:
+
+dev1: NAN_TRANSMIT handle=5 req_instance_id=7 address=02:00:00:00:00:00 ssi=aabbccdd
+
+Subscriber receiving the Follow-up message:
+
+event on dev0: <3>NAN-RECEIVE id=7 peer_instance_id=5 address=02:00:00:00:01:00 ssi=aabbccdd
+
+Stop Subscribe and Publish functions:
+
+dev0: NAN_CANCEL_SUBSCRIBE subscribe_id=7
+dev1: NAN_CANCEL_PUBLIST publish_id=5
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index 4cc3808..42e2237 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -564,4 +564,19 @@
# WPA3-Personal (SAE) PK (Public Key) mode
CONFIG_SAE_PK=y
+# Disable support for Radio Measurement (IEEE 802.11k) and supported operating
+# class indication. Removing these is not recommended since they can help the
+# AP manage the network and STA steering.
+#CONFIG_NO_RRM=y
+
+# Disable support for Robust AV streaming for consumer and enterprise Wi-Fi
+# applications; IEEE Std 802.11-2020, 4.3.24; SCS, MSCS, QoS Management
+#CONFIG_NO_ROBUST_AV=y
+
+# Disable support for WMM admission control
+#CONFIG_NO_WMM_AC=y
+
+# Wi-Fi Aware unsynchronized service discovery (NAN USD)
+#CONFIG_NAN_USD=y
+
include $(wildcard $(LOCAL_PATH)/android_config_*.inc)
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 1b94fe5..000914a 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -1848,6 +1848,8 @@
if (ret)
return ret;
+ settings.link_id = -1;
+
return ap_switch_channel(wpa_s, &settings);
}
#endif /* CONFIG_CTRL_IFACE */
diff --git a/wpa_supplicant/bgscan.h b/wpa_supplicant/bgscan.h
index 3df1550..4388b4e 100644
--- a/wpa_supplicant/bgscan.h
+++ b/wpa_supplicant/bgscan.h
@@ -51,7 +51,7 @@
#else /* CONFIG_BGSCAN */
static inline int bgscan_init(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid, const char name)
+ struct wpa_ssid *ssid, const char *name)
{
return 0;
}
diff --git a/wpa_supplicant/bgscan_learn.c b/wpa_supplicant/bgscan_learn.c
index 9830c4a..cab4ae2 100644
--- a/wpa_supplicant/bgscan_learn.c
+++ b/wpa_supplicant/bgscan_learn.c
@@ -57,7 +57,7 @@
return 0;
for (i = 0; i < array_len; i++) {
- if (os_memcmp(array + i * ETH_ALEN, bssid, ETH_ALEN) == 0)
+ if (ether_addr_equal(array + i * ETH_ALEN, bssid))
return 1;
}
@@ -70,7 +70,7 @@
{
u8 *n;
- if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
+ if (ether_addr_equal(bss->bssid, bssid))
return;
if (bssid_in_array(bss->neigh, bss->num_neigh, bssid))
return;
@@ -91,7 +91,7 @@
struct bgscan_learn_bss *bss;
dl_list_for_each(bss, &data->bss, struct bgscan_learn_bss, list) {
- if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
+ if (ether_addr_equal(bss->bssid, bssid))
return bss;
}
return NULL;
diff --git a/wpa_supplicant/bgscan_simple.c b/wpa_supplicant/bgscan_simple.c
index f398b85..a90cf86 100644
--- a/wpa_supplicant/bgscan_simple.c
+++ b/wpa_supplicant/bgscan_simple.c
@@ -15,11 +15,16 @@
#include "wpa_supplicant_i.h"
#include "driver_i.h"
#include "scan.h"
+#include "config.h"
+#include "wnm_sta.h"
+#include "bss.h"
#include "bgscan.h"
struct bgscan_simple_data {
struct wpa_supplicant *wpa_s;
const struct wpa_ssid *ssid;
+ unsigned int use_btm_query;
+ unsigned int scan_action_count;
int scan_interval;
int signal_threshold;
int short_scan_count; /* counter for scans using short scan interval */
@@ -30,12 +35,54 @@
};
+static void bgscan_simple_timeout(void *eloop_ctx, void *timeout_ctx);
+
+
+static bool bgscan_simple_btm_query(struct wpa_supplicant *wpa_s,
+ struct bgscan_simple_data *data)
+{
+ unsigned int mod;
+
+ if (!data->use_btm_query || wpa_s->conf->disable_btm ||
+ !wpa_s->current_bss ||
+ !wpa_bss_ext_capab(wpa_s->current_bss,
+ WLAN_EXT_CAPAB_BSS_TRANSITION))
+ return false;
+
+ /* Try BTM x times, scan on x + 1 */
+ data->scan_action_count++;
+ mod = data->scan_action_count % (data->use_btm_query + 1);
+ if (mod >= data->use_btm_query)
+ return false;
+
+ wpa_printf(MSG_DEBUG,
+ "bgscan simple: Send BSS transition management query %d/%d",
+ mod, data->use_btm_query);
+ if (wnm_send_bss_transition_mgmt_query(
+ wpa_s, WNM_TRANSITION_REASON_BETTER_AP_FOUND, NULL, 0)) {
+ wpa_printf(MSG_DEBUG,
+ "bgscan simple: Failed to send BSS transition management query");
+ /* Fall through and do regular scan */
+ return false;
+ }
+
+ /* Start a new timeout for the next one. We don't have scan callback to
+ * otherwise trigger future progress when using BTM path. */
+ eloop_register_timeout(data->scan_interval, 0,
+ bgscan_simple_timeout, data, NULL);
+ return true;
+}
+
+
static void bgscan_simple_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct bgscan_simple_data *data = eloop_ctx;
struct wpa_supplicant *wpa_s = data->wpa_s;
struct wpa_driver_scan_params params;
+ if (bgscan_simple_btm_query(wpa_s, data))
+ goto scan_ok;
+
os_memset(¶ms, 0, sizeof(params));
params.num_ssids = 1;
params.ssids[0].ssid = data->ssid->ssid;
@@ -54,6 +101,7 @@
eloop_register_timeout(data->scan_interval, 0,
bgscan_simple_timeout, data, NULL);
} else {
+ scan_ok:
if (data->scan_interval == data->short_interval) {
data->short_scan_count++;
if (data->short_scan_count >= data->max_short_scans) {
@@ -80,6 +128,8 @@
{
const char *pos;
+ data->use_btm_query = 0;
+
data->short_interval = atoi(params);
pos = os_strchr(params, ':');
@@ -95,6 +145,11 @@
}
pos++;
data->long_interval = atoi(pos);
+ pos = os_strchr(pos, ':');
+ if (pos) {
+ pos++;
+ data->use_btm_query = atoi(pos);
+ }
return 0;
}
@@ -134,6 +189,7 @@
data->scan_interval = data->short_interval;
data->max_short_scans = data->long_interval / data->short_interval + 1;
if (data->signal_threshold) {
+ wpa_s->signal_threshold = data->signal_threshold;
/* Poll for signal info to set initial scan interval */
struct wpa_signal_info siginfo;
if (wpa_drv_signal_poll(wpa_s, &siginfo) == 0 &&
@@ -161,8 +217,10 @@
{
struct bgscan_simple_data *data = priv;
eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
- if (data->signal_threshold)
+ if (data->signal_threshold) {
+ data->wpa_s->signal_threshold = 0;
wpa_drv_signal_monitor(data->wpa_s, 0, 0);
+ }
os_free(data);
}
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index c1be660..22b694c 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -13,10 +13,12 @@
#include "common/ieee802_11_defs.h"
#include "drivers/driver.h"
#include "eap_peer/eap.h"
+#include "rsn_supp/wpa.h"
#include "wpa_supplicant_i.h"
#include "config.h"
#include "notify.h"
#include "scan.h"
+#include "bssid_ignore.h"
#include "bss.h"
static void wpa_bss_set_hessid(struct wpa_bss *bss)
@@ -263,7 +265,7 @@
if (bssid && !wpa_supplicant_filter_bssid_match(wpa_s, bssid))
return NULL;
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
- if ((!bssid || os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0) &&
+ if ((!bssid || ether_addr_equal(bss->bssid, bssid)) &&
bss->ssid_len == ssid_len &&
os_memcmp(bss->ssid, ssid, ssid_len) == 0)
return bss;
@@ -358,12 +360,11 @@
#ifdef CONFIG_P2P
u8 addr[ETH_ALEN];
- if (os_memcmp(bss->bssid, wpa_s->pending_join_iface_addr,
- ETH_ALEN) == 0)
+ if (ether_addr_equal(bss->bssid, wpa_s->pending_join_iface_addr))
return true;
if (!is_zero_ether_addr(wpa_s->pending_join_dev_addr) &&
p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len, addr) == 0 &&
- os_memcmp(addr, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0)
+ ether_addr_equal(addr, wpa_s->pending_join_dev_addr))
return true;
#endif /* CONFIG_P2P */
return false;
@@ -406,8 +407,8 @@
return 0; /* SSID has changed */
if (!is_zero_ether_addr(bss->bssid) &&
- (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) == 0 ||
- os_memcmp(bss->bssid, wpa_s->pending_bssid, ETH_ALEN) == 0))
+ (ether_addr_equal(bss->bssid, wpa_s->bssid) ||
+ ether_addr_equal(bss->bssid, wpa_s->pending_bssid)))
return 1;
if (!wpa_s->valid_links)
@@ -417,7 +418,7 @@
if (!(wpa_s->valid_links & BIT(i)))
continue;
- if (os_memcmp(bss->bssid, wpa_s->links[i].bssid, ETH_ALEN) == 0)
+ if (ether_addr_equal(bss->bssid, wpa_s->links[i].bssid))
return 1;
}
@@ -717,7 +718,8 @@
dl_list_del(&bss->list);
#ifdef CONFIG_P2P
if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) &&
- !wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE)) {
+ !wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE) &&
+ !(changes & WPA_BSS_FREQ_CHANGED_FLAG)) {
/*
* This can happen when non-P2P station interface runs a scan
* without P2P IE in the Probe Request frame. P2P GO would reply
@@ -1101,7 +1103,7 @@
if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
return NULL;
dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
- if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
+ if (ether_addr_equal(bss->bssid, bssid))
return bss;
}
return NULL;
@@ -1126,7 +1128,7 @@
if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
return NULL;
dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
- if (os_memcmp(bss->bssid, bssid, ETH_ALEN) != 0)
+ if (!ether_addr_equal(bss->bssid, bssid))
continue;
if (found == NULL ||
os_reltime_before(&found->last_update, &bss->last_update))
@@ -1155,7 +1157,7 @@
u8 addr[ETH_ALEN];
if (p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len,
addr) != 0 ||
- os_memcmp(addr, dev_addr, ETH_ALEN) != 0)
+ !ether_addr_equal(addr, dev_addr))
continue;
if (!found ||
os_reltime_before(&found->last_update, &bss->last_update))
@@ -1222,22 +1224,6 @@
/**
- * wpa_bss_get_ie_nth - Fetch a specified information element from a BSS entry
- * @bss: BSS table entry
- * @ie: Information element identitifier (WLAN_EID_*)
- * @nth: Return the nth element of the requested type (2 returns the second)
- * Returns: Pointer to the information element (id field) or %NULL if not found
- *
- * This function returns the nth matching information element in the BSS
- * entry.
- */
-const u8 * wpa_bss_get_ie_nth(const struct wpa_bss *bss, u8 ie, int nth)
-{
- return get_ie_nth(wpa_bss_ie_ptr(bss), bss->ie_len, ie, nth);
-}
-
-
-/**
* wpa_bss_get_ie_ext - Fetch a specified extended IE from a BSS entry
* @bss: BSS table entry
* @ext: Information element extension identifier (WLAN_EID_EXT_*)
@@ -1496,29 +1482,12 @@
}
-/**
- * wpa_bss_defrag_mle - Get a buffer holding a de-fragmented ML element
- * @bss: BSS table entry
- * @type: ML control type
- */
-struct wpabuf * wpa_bss_defrag_mle(const struct wpa_bss *bss, u8 type)
-{
- struct ieee802_11_elems elems;
- const u8 *pos = wpa_bss_ie_ptr(bss);
- size_t len = bss->ie_len;
-
- if (ieee802_11_parse_elems(pos, len, &elems, 1) == ParseFailed)
- return NULL;
-
- return ieee802_11_defrag_mle(&elems, type);
-}
-
-
static void
wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, u8 mbssid_idx,
const struct ieee80211_neighbor_ap_info *ap_info,
- size_t len, u16 *seen, u16 *missing)
+ size_t len, u16 *seen, u16 *missing,
+ struct wpa_ssid *ssid)
{
const u8 *pos, *end;
const u8 *mld_params;
@@ -1542,12 +1511,15 @@
pos += sizeof(*ap_info);
for (i = 0; i < count; i++) {
+ u8 bss_params;
+
if (bss->n_mld_links >= MAX_NUM_MLD_LINKS)
return;
if (end - pos < ap_info->tbtt_info_len)
break;
+ bss_params = pos[1 + ETH_ALEN + 4];
mld_params = pos + mld_params_offset;
link_id = *(mld_params + 1) & EHT_ML_LINK_ID_MSK;
@@ -1557,23 +1529,30 @@
"MLD: Reported link not part of MLD");
} else if (!(BIT(link_id) & *seen)) {
struct wpa_bss *neigh_bss =
- wpa_bss_get_bssid(wpa_s, ap_info->data + 1);
+ wpa_bss_get_bssid(wpa_s, pos + 1);
*seen |= BIT(link_id);
wpa_printf(MSG_DEBUG, "MLD: mld ID=%u, link ID=%u",
*mld_params, link_id);
- if (neigh_bss) {
+ if (!neigh_bss) {
+ *missing |= BIT(link_id);
+ } else if ((!ssid ||
+ (bss_params & (RNR_BSS_PARAM_SAME_SSID |
+ RNR_BSS_PARAM_CO_LOCATED)) ||
+ wpa_scan_res_match(wpa_s, 0, neigh_bss,
+ ssid, 1, 0)) &&
+ !wpa_bssid_ignore_is_listed(
+ wpa_s, neigh_bss->bssid)) {
struct mld_link *l;
l = &bss->mld_links[bss->n_mld_links];
l->link_id = link_id;
- os_memcpy(l->bssid, ap_info->data + 1,
- ETH_ALEN);
+ os_memcpy(l->bssid, pos + 1, ETH_ALEN);
l->freq = neigh_bss->freq;
+ l->disabled = mld_params[2] &
+ RNR_TBTT_INFO_MLD_PARAM2_LINK_DISABLED;
bss->n_mld_links++;
- } else {
- *missing |= BIT(link_id);
}
}
@@ -1590,6 +1569,8 @@
* @link_info: Array to store link information (or %NULL),
* should be initialized and #MAX_NUM_MLD_LINKS elements long
* @missing_links: Result bitmask of links that were not discovered (or %NULL)
+ * @ssid: Target SSID (or %NULL)
+ * @ap_mld_id: On return would hold the corresponding AP MLD ID (or %NULL)
* Returns: 0 on success or -1 for non-MLD or parsing failures
*
* Parses the Basic Multi-Link element of the BSS into @link_info using the scan
@@ -1600,13 +1581,15 @@
int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss,
u8 *ap_mld_addr,
- u16 *missing_links)
+ u16 *missing_links,
+ struct wpa_ssid *ssid,
+ u8 *ap_mld_id)
{
struct ieee802_11_elems elems;
struct wpabuf *mlbuf;
const struct element *elem;
u8 mbssid_idx = 0;
- u8 ml_ie_len;
+ size_t ml_ie_len;
const struct ieee80211_eht_ml *eht_ml;
const struct eht_ml_basic_common_info *ml_basic_common_info;
u8 i, link_id;
@@ -1633,7 +1616,7 @@
return ret;
}
- mlbuf = ieee802_11_defrag_mle(&elems, MULTI_LINK_CONTROL_TYPE_BASIC);
+ mlbuf = ieee802_11_defrag(elems.basic_mle, elems.basic_mle_len, true);
if (!mlbuf) {
wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No Multi-Link element");
return ret;
@@ -1641,6 +1624,32 @@
ml_ie_len = wpabuf_len(mlbuf);
+ if (ssid) {
+ struct wpa_ie_data ie;
+
+ if (!elems.rsn_ie ||
+ wpa_parse_wpa_ie(elems.rsn_ie - 2, 2 + elems.rsn_ie_len,
+ &ie)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RSN element");
+ goto out;
+ }
+
+ if (!(ie.capabilities & WPA_CAPABILITY_MFPC) ||
+ wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "MLD: No management frame protection");
+ goto out;
+ }
+
+ ie.key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK |
+ WPA_KEY_MGMT_PSK_SHA256);
+ if (!(ie.key_mgmt & ssid->key_mgmt)) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "MLD: No valid key management");
+ goto out;
+ }
+ }
+
/*
* for ext ID + 2 control + common info len + MLD address +
* link info
@@ -1720,7 +1729,7 @@
wpa_bss_parse_ml_rnr_ap_info(wpa_s, bss, mbssid_idx,
ap_info, len, &seen,
- &missing);
+ &missing, ssid);
pos += ap_info_len;
len -= ap_info_len;
@@ -1739,6 +1748,9 @@
if (missing_links)
*missing_links = missing;
+ if (ap_mld_id)
+ *ap_mld_id = mbssid_idx;
+
ret = 0;
out:
wpabuf_free(mlbuf);
@@ -1769,7 +1781,7 @@
if (!elems.reconf_mle || !elems.reconf_mle_len)
return 0;
- mlbuf = ieee802_11_defrag_mle(&elems, MULTI_LINK_CONTROL_TYPE_RECONF);
+ mlbuf = ieee802_11_defrag(elems.reconf_mle, elems.reconf_mle_len, true);
if (!mlbuf)
return 0;
diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h
index 042b5d2..c06c20a 100644
--- a/wpa_supplicant/bss.h
+++ b/wpa_supplicant/bss.h
@@ -133,6 +133,9 @@
u8 link_id;
u8 bssid[ETH_ALEN];
int freq;
+
+ /* Whether the link is valid but currently disabled */
+ bool disabled;
} mld_links[MAX_NUM_MLD_LINKS];
/* followed by ie_len octets of IEs */
@@ -171,7 +174,6 @@
struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s,
unsigned int idf, unsigned int idl);
const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie);
-const u8 * wpa_bss_get_ie_nth(const struct wpa_bss *bss, u8 ie, int nth);
const u8 * wpa_bss_get_ie_ext(const struct wpa_bss *bss, u8 ext);
const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type);
const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss,
@@ -213,11 +215,12 @@
unsigned int age_ms,
struct os_reltime *update_time);
-struct wpabuf * wpa_bss_defrag_mle(const struct wpa_bss *bss, u8 type);
int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss,
u8 *ap_mld_addr,
- u16 *missing_links);
+ u16 *missing_links,
+ struct wpa_ssid *ssid,
+ u8 *ap_mld_id);
u16 wpa_bss_parse_reconf_ml_element(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss);
diff --git a/wpa_supplicant/bssid_ignore.c b/wpa_supplicant/bssid_ignore.c
index e378577..ab16fc5 100644
--- a/wpa_supplicant/bssid_ignore.c
+++ b/wpa_supplicant/bssid_ignore.c
@@ -37,7 +37,7 @@
e = wpa_s->bssid_ignore;
while (e) {
- if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0)
+ if (ether_addr_equal(e->bssid, bssid))
return e;
e = e->next;
}
@@ -85,9 +85,9 @@
e->timeout_secs = 60;
else
e->timeout_secs = 10;
- wpa_printf(MSG_INFO, "BSSID " MACSTR
- " ignore list count incremented to %d, ignoring for %d seconds",
- MAC2STR(bssid), e->count, e->timeout_secs);
+ wpa_msg(wpa_s, MSG_INFO, "BSSID " MACSTR
+ " ignore list count incremented to %d, ignoring for %d seconds",
+ MAC2STR(bssid), e->count, e->timeout_secs);
return e->count;
}
@@ -100,9 +100,9 @@
e->start = now;
e->next = wpa_s->bssid_ignore;
wpa_s->bssid_ignore = e;
- wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR
- " into ignore list, ignoring for %d seconds",
- MAC2STR(bssid), e->timeout_secs);
+ wpa_msg(wpa_s, MSG_INFO, "Added BSSID " MACSTR
+ " into ignore list, ignoring for %d seconds",
+ MAC2STR(bssid), e->timeout_secs);
return e->count;
}
@@ -123,14 +123,14 @@
e = wpa_s->bssid_ignore;
while (e) {
- if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) {
+ if (ether_addr_equal(e->bssid, bssid)) {
if (prev == NULL) {
wpa_s->bssid_ignore = e->next;
} else {
prev->next = e->next;
}
- wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR
- " from ignore list", MAC2STR(bssid));
+ wpa_msg(wpa_s, MSG_INFO, "Removed BSSID " MACSTR
+ " from ignore list", MAC2STR(bssid));
os_free(e);
return 0;
}
@@ -175,8 +175,8 @@
while (e) {
prev = e;
e = e->next;
- wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR
- " from ignore list (clear)", MAC2STR(prev->bssid));
+ wpa_msg(wpa_s, MSG_INFO, "Removed BSSID " MACSTR
+ " from ignore list (clear)", MAC2STR(prev->bssid));
os_free(prev);
}
}
@@ -209,9 +209,9 @@
wpa_s->bssid_ignore = e->next;
e = wpa_s->bssid_ignore;
}
- wpa_printf(MSG_INFO, "Removed BSSID " MACSTR
- " from ignore list (expired)",
- MAC2STR(to_delete->bssid));
+ wpa_msg(wpa_s, MSG_INFO, "Removed BSSID " MACSTR
+ " from ignore list (expired)",
+ MAC2STR(to_delete->bssid));
os_free(to_delete);
} else {
prev = e;
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index d1d8ca3..8c0db68 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2368,7 +2368,7 @@
u8 mac_value[ETH_ALEN];
if (hwaddr_aton(value, mac_value) == 0) {
- if (os_memcmp(mac_value, ssid->mac_value, ETH_ALEN) == 0)
+ if (ether_addr_equal(mac_value, ssid->mac_value))
return 1;
os_memcpy(ssid->mac_value, mac_value, ETH_ALEN);
return 0;
@@ -4681,6 +4681,10 @@
config->driver_param = os_strdup(driver_param);
config->gas_rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME;
+#ifdef CONFIG_TESTING_OPTIONS
+ config->mld_connect_band_pref = DEFAULT_MLD_CONNECT_BAND_PREF;
+#endif /* CONFIG_TESTING_OPTIONS */
+
return config;
}
@@ -5315,6 +5319,23 @@
#endif /* CONFIG_P2P */
+#ifdef CONFIG_TESTING_OPTIONS
+static int wpa_config_process_mld_connect_bssid_pref(
+ const struct global_parse_data *data,
+ struct wpa_config *config, int line, const char *pos)
+{
+ if (hwaddr_aton2(pos, config->mld_connect_bssid_pref) < 0) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid mld_connect_bssid_pref '%s'",
+ line, pos);
+ return -1;
+ }
+
+ return 0;
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+
#ifdef OFFSET
#undef OFFSET
#endif /* OFFSET */
@@ -5531,6 +5552,15 @@
{ INT_RANGE(pasn_corrupt_mic, 0, 1), 0 },
#endif /* CONFIG_TESTING_OPTIONS */
#endif /* CONFIG_PASN */
+#ifdef CONFIG_TESTING_OPTIONS
+ { INT_RANGE(mld_force_single_link, 0, 1), 0 },
+ { INT_RANGE(mld_connect_band_pref, 0, MLD_CONNECT_BAND_PREF_MAX), 0 },
+ { FUNC(mld_connect_bssid_pref), 0 },
+#endif /* CONFIG_TESTING_OPTIONS */
+ { INT_RANGE(ft_prepend_pmkid, 0, 1), CFG_CHANGED_FT_PREPEND_PMKID },
+ /* NOTE: When adding new parameters here, add_interface() in
+ * wpa_supplicant/dbus_new_introspect.c may need to be modified to
+ * increase the size of the iface->xml buffer. */
};
#undef FUNC
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 09bcbc8..56d5c61 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -48,6 +48,7 @@
#define DEFAULT_EXTENDED_KEY_ID 0
#define DEFAULT_BTM_OFFLOAD 0
#define DEFAULT_SCAN_RES_VALID_FOR_CONNECT 5
+#define DEFAULT_MLD_CONNECT_BAND_PREF MLD_CONNECT_BAND_PREF_AUTO
#include "config_ssid.h"
#include "wps/wps.h"
@@ -451,7 +452,8 @@
#define CFG_CHANGED_WOWLAN_TRIGGERS BIT(18)
#define CFG_CHANGED_DISABLE_BTM BIT(19)
#define CFG_CHANGED_BGSCAN BIT(20)
-#define CFG_CHANGED_DISABLE_BTM_NOTIFY BIT(21)
+#define CFG_CHANGED_FT_PREPEND_PMKID BIT(21)
+#define CFG_CHANGED_DISABLE_BTM_NOTIFY BIT(22)
/**
* struct wpa_config - wpa_supplicant configuration data
@@ -726,6 +728,14 @@
unsigned int dot11RSNAConfigSATimeout;
/**
+ * ft_prepend_pmkid - Whether to prepend PMKR1Name with PMKIDs
+ *
+ * This control whether PMKR1Name is prepended to the PMKID list
+ * insread of replacing the full list when constructing RSNE for
+ * EAPOL-Key msg 2/4 for FT cases. */
+ bool ft_prepend_pmkid;
+
+ /**
* update_config - Is wpa_supplicant allowed to update configuration
*
* This variable control whether wpa_supplicant is allow to re-write
@@ -1806,6 +1816,20 @@
#endif /* CONFIG_TESTING_OPTIONS */
#endif /* CONFIG_PASN*/
+
+#ifdef CONFIG_TESTING_OPTIONS
+ enum {
+ MLD_CONNECT_BAND_PREF_AUTO = 0,
+ MLD_CONNECT_BAND_PREF_2GHZ = 1,
+ MLD_CONNECT_BAND_PREF_5GHZ = 2,
+ MLD_CONNECT_BAND_PREF_6GHZ = 3,
+ MLD_CONNECT_BAND_PREF_MAX = 4,
+ } mld_connect_band_pref;
+
+ u8 mld_connect_bssid_pref[ETH_ALEN];
+
+ int mld_force_single_link;
+#endif /* CONFIG_TESTING_OPTIONS */
};
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index ebad5f1..71a64b1 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -1618,6 +1618,18 @@
if (config->wowlan_disconnect_on_deinit)
fprintf(f, "wowlan_disconnect_on_deinit=%d\n",
config->wowlan_disconnect_on_deinit);
+#ifdef CONFIG_TESTING_OPTIONS
+ if (config->mld_force_single_link)
+ fprintf(f, "mld_force_single_link=1\n");
+ if (config->mld_connect_band_pref != MLD_CONNECT_BAND_PREF_AUTO)
+ fprintf(f, "mld_connect_band_pref=%d\n",
+ config->mld_connect_band_pref);
+ if (!is_zero_ether_addr(config->mld_connect_bssid_pref))
+ fprintf(f, "mld_connect_bssid_pref=" MACSTR "\n",
+ MAC2STR(config->mld_connect_bssid_pref));
+#endif /* CONFIG_TESTING_OPTIONS */
+ if (config->ft_prepend_pmkid)
+ fprintf(f, "ft_prepend_pmkid=%d", config->ft_prepend_pmkid);
}
#endif /* CONFIG_NO_CONFIG_WRITE */
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index a68802e..500f4d1 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant / Control interface (shared code for all backends)
- * Copyright (c) 2004-2020, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2024, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -22,6 +22,7 @@
#ifdef CONFIG_DPP
#include "common/dpp.h"
#endif /* CONFIG_DPP */
+#include "common/nan_de.h"
#include "common/ptksa_cache.h"
#include "crypto/tls.h"
#include "ap/hostapd.h"
@@ -58,6 +59,7 @@
#include "mesh.h"
#include "dpp_supplicant.h"
#include "sme.h"
+#include "nan_usd.h"
#ifdef __NetBSD__
#include <net/if_ether.h>
@@ -445,7 +447,7 @@
dl_list_for_each(tmp, &wpa_s->drv_signal_override,
struct driver_signal_override, list) {
- if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
+ if (ether_addr_equal(bssid, tmp->bssid)) {
dso = tmp;
break;
}
@@ -739,6 +741,12 @@
wpa_s->ext_eapol_frame_io;
}
#endif /* CONFIG_AP */
+ } else if (os_strcasecmp(cmd, "encrypt_eapol_m2") == 0) {
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M2,
+ !!atoi(value));
+ } else if (os_strcasecmp(cmd, "encrypt_eapol_m4") == 0) {
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M4,
+ !!atoi(value));
} else if (os_strcasecmp(cmd, "extra_roc_dur") == 0) {
wpa_s->extra_roc_dur = atoi(value);
} else if (os_strcasecmp(cmd, "test_failure") == 0) {
@@ -833,15 +841,19 @@
wpa_s->sae_commit_override = wpabuf_parse_bin(value);
} else if (os_strcasecmp(cmd, "driver_signal_override") == 0) {
ret = wpas_ctrl_iface_set_dso(wpa_s, value);
+#ifndef CONFIG_NO_ROBUST_AV
} else if (os_strcasecmp(cmd, "disable_scs_support") == 0) {
wpa_s->disable_scs_support = !!atoi(value);
} else if (os_strcasecmp(cmd, "disable_mscs_support") == 0) {
wpa_s->disable_mscs_support = !!atoi(value);
+#endif /* CONFIG_NO_ROBUST_AV */
} else if (os_strcasecmp(cmd, "disable_eapol_g2_tx") == 0) {
wpa_s->disable_eapol_g2_tx = !!atoi(value);
/* Populate value to wpa_sm if already associated. */
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
wpa_s->disable_eapol_g2_tx);
+ } else if (os_strcasecmp(cmd, "test_assoc_comeback_type") == 0) {
+ wpa_s->test_assoc_comeback_type = atoi(value);
#ifdef CONFIG_DPP
} else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
os_free(wpa_s->dpp_config_obj_override);
@@ -932,8 +944,10 @@
return -1;
wnm_set_coloc_intf_elems(wpa_s, elems);
#endif /* CONFIG_WNM */
+#ifndef CONFIG_NO_ROBUST_AV
} else if (os_strcasecmp(cmd, "enable_dscp_policy_capa") == 0) {
wpa_s->enable_dscp_policy_capa = !!atoi(value);
+#endif /* CONFIG_NO_ROBUST_AV */
} else {
value[-1] = '=';
ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
@@ -1260,6 +1274,8 @@
#endif /* CONFIG_TDLS */
+#ifndef CONFIG_NO_WMM_AC
+
static int wmm_ac_ctrl_addts(struct wpa_supplicant *wpa_s, char *cmd)
{
char *token, *context = NULL;
@@ -1309,6 +1325,8 @@
return wpas_wmm_ac_delts(wpa_s, tsid);
}
+#endif /* CONFIG_NO_WMM_AC */
+
#ifdef CONFIG_IEEE80211R
static int wpa_supplicant_ctrl_iface_ft_ds(
@@ -3618,7 +3636,7 @@
#endif /* CONFIG_BGSCAN */
if (os_strcmp(name, "bssid") != 0 &&
- os_strcmp(name, "bssid_hint") != 0 &&
+ os_strncmp(name, "bssid_", 6) != 0 &&
os_strcmp(name, "scan_freq") != 0 &&
os_strcmp(name, "priority") != 0) {
wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
@@ -3683,7 +3701,7 @@
value);
if (ret == 0 &&
(ssid->bssid_set != prev_bssid_set ||
- os_memcmp(ssid->bssid, prev_bssid, ETH_ALEN) != 0))
+ !ether_addr_equal(ssid->bssid, prev_bssid)))
wpas_notify_network_bssid_set_changed(wpa_s, ssid);
if (prev_disabled != ssid->disabled &&
@@ -4859,6 +4877,15 @@
}
#endif /* CONFIG_DPP */
+#ifdef CONFIG_NAN_USD
+ if (os_strcmp(field, "nan") == 0) {
+ res = os_snprintf(buf, buflen, "USD");
+ if (os_snprintf_error(buflen, res))
+ return -1;
+ return res;
+ }
+#endif /* CONFIG_NAN_USD */
+
#ifdef CONFIG_SAE
if (os_strcmp(field, "sae") == 0 &&
(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
@@ -4954,7 +4981,7 @@
ie_end = ie + 2 + ie[1];
ie += 2;
if (ie_end - ie < 2)
- return -1;
+ return 0;
info = WPA_GET_LE16(ie);
ie += 2;
@@ -4966,7 +4993,7 @@
if (info & BIT(7)) {
/* Cache Identifier Included */
if (ie_end - ie < 2)
- return -1;
+ return 0;
ret = os_snprintf(pos, end - pos, "fils_cache_id=%02x%02x\n",
ie[0], ie[1]);
if (os_snprintf_error(end - pos, ret))
@@ -4978,7 +5005,7 @@
if (info & BIT(8)) {
/* HESSID Included */
if (ie_end - ie < ETH_ALEN)
- return -1;
+ return 0;
ret = os_snprintf(pos, end - pos, "fils_hessid=" MACSTR "\n",
MAC2STR(ie));
if (os_snprintf_error(end - pos, ret))
@@ -4990,7 +5017,7 @@
realms = (info & (BIT(3) | BIT(4) | BIT(5))) >> 3;
if (realms) {
if (ie_end - ie < realms * 2)
- return -1;
+ return 0;
ret = os_snprintf(pos, end - pos, "fils_realms=");
if (os_snprintf_error(end - pos, ret))
return 0;
@@ -5244,7 +5271,7 @@
if (common_info_length < 1)
return 0;
- ret = os_snprintf(pos, end - pos, ", MLD ID=0x%x\n", *ie);
+ ret = os_snprintf(pos, end - pos, ", MLD ID=0x%x", *ie);
if (os_snprintf_error(end - pos, ret))
return 0;
pos += ret;
@@ -5252,6 +5279,11 @@
common_info_length--;
}
+ ret = os_snprintf(pos, end - pos, "\n");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+
return pos - start;
}
@@ -5386,13 +5418,13 @@
if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
if (os_snprintf_error(end - pos, ret))
- return -1;
+ return 0;
pos += ret;
}
if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
ret = os_snprintf(pos, end - pos, "[SAE-PK]");
if (os_snprintf_error(end - pos, ret))
- return -1;
+ return 0;
pos += ret;
}
osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
@@ -5691,8 +5723,6 @@
#ifdef CONFIG_FILS
if (mask & WPA_BSS_MASK_FILS_INDICATION) {
ret = print_fils_indication(bss, pos, end);
- if (ret < 0)
- return 0;
pos += ret;
}
#endif /* CONFIG_FILS */
@@ -6289,32 +6319,6 @@
}
-static int parse_freq(int chwidth, int freq2)
-{
- if (freq2 < 0)
- return -1;
- if (freq2)
- return CONF_OPER_CHWIDTH_80P80MHZ;
-
- switch (chwidth) {
- case 0:
- case 20:
- case 40:
- return CONF_OPER_CHWIDTH_USE_HT;
- case 80:
- return CONF_OPER_CHWIDTH_80MHZ;
- case 160:
- return CONF_OPER_CHWIDTH_160MHZ;
- case 320:
- return CONF_OPER_CHWIDTH_320MHZ;
- default:
- wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d",
- chwidth);
- return -1;
- }
-}
-
-
static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
char *buf, size_t buflen)
{
@@ -6408,7 +6412,7 @@
if (pos2)
chwidth = atoi(pos2 + 18);
- max_oper_chwidth = parse_freq(chwidth, freq2);
+ max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
if (max_oper_chwidth < 0)
return -1;
@@ -7062,7 +7066,7 @@
if (pos)
chwidth = atoi(pos + 18);
- max_oper_chwidth = parse_freq(chwidth, freq2);
+ max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
if (max_oper_chwidth < 0)
return -1;
@@ -7138,8 +7142,8 @@
return -1;
}
- return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
- vht_center_freq2, 0, ht40, vht,
+ return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0,
+ vht_center_freq2, ht40, vht,
vht_chwidth, he, edmg,
NULL, 0, 0, allow_6ghz, 0,
go_bssid);
@@ -7217,7 +7221,7 @@
}
#endif /* CONFIG_ACS */
- max_oper_chwidth = parse_freq(chwidth, freq2);
+ max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
if (max_oper_chwidth < 0)
return -1;
@@ -7837,7 +7841,7 @@
dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss,
list) {
- if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
+ if (ether_addr_equal(bss->bssid, bssid) &&
bss->ssid_len > 0) {
found = 1;
break;
@@ -8004,11 +8008,11 @@
dialog_token = atoi(pos);
if (wpa_s->last_gas_resp &&
- os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 &&
+ ether_addr_equal(addr, wpa_s->last_gas_addr) &&
dialog_token == wpa_s->last_gas_dialog_token)
resp = wpa_s->last_gas_resp;
else if (wpa_s->prev_gas_resp &&
- os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 &&
+ ether_addr_equal(addr, wpa_s->prev_gas_addr) &&
dialog_token == wpa_s->prev_gas_dialog_token)
resp = wpa_s->prev_gas_resp;
else
@@ -8867,6 +8871,10 @@
wpa_s->ft_rsnxe_used = 0;
wpa_s->reject_btm_req_reason = 0;
wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
+ wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, NULL);
+ wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, NULL);
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M2, 0);
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M4, 0);
os_free(wpa_s->get_pref_freq_list_override);
wpa_s->get_pref_freq_list_override = NULL;
wpabuf_free(wpa_s->sae_commit_override);
@@ -8880,9 +8888,11 @@
wpabuf_free(wpa_s->rsnxe_override_eapol);
wpa_s->rsnxe_override_eapol = NULL;
wpas_clear_driver_signal_override(wpa_s);
+#ifndef CONFIG_NO_ROBUST_AV
wpa_s->disable_scs_support = 0;
wpa_s->disable_mscs_support = 0;
wpa_s->enable_dscp_policy_capa = 0;
+#endif /* CONFIG_NO_ROBUST_AV */
wpa_s->oci_freq_override_eapol = 0;
wpa_s->oci_freq_override_saquery_req = 0;
wpa_s->oci_freq_override_saquery_resp = 0;
@@ -8891,6 +8901,7 @@
wpa_s->oci_freq_override_fils_assoc = 0;
wpa_s->oci_freq_override_wnm_sleep = 0;
wpa_s->disable_eapol_g2_tx = 0;
+ wpa_s->test_assoc_comeback_type = -1;
#ifdef CONFIG_DPP
os_free(wpa_s->dpp_config_obj_override);
wpa_s->dpp_config_obj_override = NULL;
@@ -8911,7 +8922,9 @@
wpa_s->next_scan_bssid_wildcard_ssid = 0;
os_free(wpa_s->select_network_scan_freqs);
wpa_s->select_network_scan_freqs = NULL;
+#ifndef CONFIG_NO_ROBUST_AV
os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
+#endif /* CONFIG_NO_ROBUST_AV */
wpa_bss_flush(wpa_s);
if (!dl_list_empty(&wpa_s->bss)) {
@@ -8938,7 +8951,9 @@
free_bss_tmp_disallowed(wpa_s);
+#ifndef CONFIG_NO_ROBUST_AV
os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
+#endif /* CONFIG_NO_ROBUST_AV */
#ifdef CONFIG_PASN
wpas_pasn_auth_stop(wpa_s);
@@ -8948,6 +8963,10 @@
wpas_restore_permanent_mac_addr(wpa_s);
wpa_s->conf->ignore_old_scan_res = 0;
+
+#ifdef CONFIG_NAN_USD
+ wpas_nan_usd_flush(wpa_s);
+#endif /* CONFIG_NAN_USD */
}
@@ -10134,72 +10153,6 @@
}
-static int wpas_ctrl_test_alloc_fail(struct wpa_supplicant *wpa_s, char *cmd)
-{
-#ifdef WPA_TRACE_BFD
- char *pos;
-
- wpa_trace_fail_after = atoi(cmd);
- pos = os_strchr(cmd, ':');
- if (pos) {
- pos++;
- os_strlcpy(wpa_trace_fail_func, pos,
- sizeof(wpa_trace_fail_func));
- } else {
- wpa_trace_fail_after = 0;
- }
- return 0;
-#else /* WPA_TRACE_BFD */
- return -1;
-#endif /* WPA_TRACE_BFD */
-}
-
-
-static int wpas_ctrl_get_alloc_fail(struct wpa_supplicant *wpa_s,
- char *buf, size_t buflen)
-{
-#ifdef WPA_TRACE_BFD
- return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
- wpa_trace_fail_func);
-#else /* WPA_TRACE_BFD */
- return -1;
-#endif /* WPA_TRACE_BFD */
-}
-
-
-static int wpas_ctrl_test_fail(struct wpa_supplicant *wpa_s, char *cmd)
-{
-#ifdef WPA_TRACE_BFD
- char *pos;
-
- wpa_trace_test_fail_after = atoi(cmd);
- pos = os_strchr(cmd, ':');
- if (pos) {
- pos++;
- os_strlcpy(wpa_trace_test_fail_func, pos,
- sizeof(wpa_trace_test_fail_func));
- } else {
- wpa_trace_test_fail_after = 0;
- }
- return 0;
-#else /* WPA_TRACE_BFD */
- return -1;
-#endif /* WPA_TRACE_BFD */
-}
-
-
-static int wpas_ctrl_get_fail(struct wpa_supplicant *wpa_s,
- char *buf, size_t buflen)
-{
-#ifdef WPA_TRACE_BFD
- return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
- wpa_trace_test_fail_func);
-#else /* WPA_TRACE_BFD */
- return -1;
-#endif /* WPA_TRACE_BFD */
-}
-
-
static void wpas_ctrl_event_test_cb(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
@@ -10227,13 +10180,12 @@
}
-static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
- const char *cmd)
+static int wpas_get_hex_buf(const char *val, struct wpabuf **ret)
{
struct wpabuf *buf;
size_t len;
- len = os_strlen(cmd);
+ len = os_strlen(val);
if (len & 1)
return -1;
len /= 2;
@@ -10242,20 +10194,56 @@
buf = NULL;
} else {
buf = wpabuf_alloc(len);
- if (buf == NULL)
+ if (!buf)
return -1;
- if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
+ if (hexstr2bin(val, wpabuf_put(buf, len), len) < 0) {
wpabuf_free(buf);
return -1;
}
}
+ *ret = buf;
+ return 0;
+}
+
+
+static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
+ const char *cmd)
+{
+ struct wpabuf *buf;
+
+ if (wpas_get_hex_buf(cmd, &buf) < 0)
+ return -1;
wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf);
return 0;
}
+static int wpas_ctrl_test_eapol_m2_elems(struct wpa_supplicant *wpa_s,
+ const char *cmd)
+{
+ struct wpabuf *buf;
+
+ if (wpas_get_hex_buf(cmd, &buf) < 0)
+ return -1;
+ wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, buf);
+ return 0;
+}
+
+
+static int wpas_ctrl_test_eapol_m4_elems(struct wpa_supplicant *wpa_s,
+ const char *cmd)
+{
+ struct wpabuf *buf;
+
+ if (wpas_get_hex_buf(cmd, &buf) < 0)
+ return -1;
+ wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, buf);
+ return 0;
+}
+
+
static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
{
u8 zero[WPA_TK_MAX_LEN];
@@ -10571,6 +10559,8 @@
}
+#ifndef CONFIG_NO_RRM
+
static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep)
{
struct wpa_supplicant *wpa_s = ctx;
@@ -10714,6 +10704,8 @@
return ret;
}
+#endif /* CONFIG_NO_RRM */
+
static int wpas_ctrl_iface_erp_flush(struct wpa_supplicant *wpa_s)
{
@@ -11067,6 +11059,7 @@
}
+#ifndef CONFIG_NO_ROBUST_AV
static int wpas_ctrl_iface_configure_mscs(struct wpa_supplicant *wpa_s,
const char *cmd)
{
@@ -11135,6 +11128,7 @@
return wpas_send_mscs_req(wpa_s);
}
+#endif /* CONFIG_NO_ROBUST_AV */
#ifdef CONFIG_PASN
@@ -11236,9 +11230,55 @@
return wpas_pasn_deauthenticate(wpa_s, wpa_s->own_addr, bssid);
}
+
+#ifdef CONFIG_TESTING_OPTIONS
+static int wpas_ctrl_iface_pasn_driver(struct wpa_supplicant *wpa_s,
+ const char *cmd)
+{
+ union wpa_event_data event;
+ const char *pos = cmd;
+ u8 addr[ETH_ALEN];
+
+ os_memset(&event, 0, sizeof(event));
+
+ if (os_strncmp(pos, "auth ", 5) == 0)
+ event.pasn_auth.action = PASN_ACTION_AUTH;
+ else if (os_strncmp(pos, "del ", 4) == 0)
+ event.pasn_auth.action =
+ PASN_ACTION_DELETE_SECURE_RANGING_CONTEXT;
+ else
+ return -1;
+
+ pos = os_strchr(pos, ' ');
+ if (!pos)
+ return -1;
+ pos++;
+ while (hwaddr_aton(pos, addr) == 0) {
+ struct pasn_peer *peer;
+
+ if (event.pasn_auth.num_peers == WPAS_MAX_PASN_PEERS)
+ return -1;
+ peer = &event.pasn_auth.peer[event.pasn_auth.num_peers];
+ os_memcpy(peer->own_addr, wpa_s->own_addr, ETH_ALEN);
+ os_memcpy(peer->peer_addr, addr, ETH_ALEN);
+ event.pasn_auth.num_peers++;
+
+ pos = os_strchr(pos, ' ');
+ if (!pos)
+ break;
+ pos++;
+ }
+
+ wpa_supplicant_event(wpa_s, EVENT_PASN_AUTH, &event);
+ return 0;
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
#endif /* CONFIG_PASN */
+#ifndef CONFIG_NO_ROBUST_AV
+
static int set_type4_frame_classifier(const char *cmd,
struct type4_params *param)
{
@@ -11935,6 +11975,8 @@
return wpas_send_dscp_query(wpa_s, pos + 12, os_strlen(pos + 12));
}
+#endif /* CONFIG_NO_ROBUST_AV */
+
static int wpas_ctrl_iface_mlo_signal_poll(struct wpa_supplicant *wpa_s,
char *buf, size_t buflen)
@@ -12121,6 +12163,327 @@
#endif /* CONFIG_TESTING_OPTIONS */
+#ifdef CONFIG_NAN_USD
+
+static int wpas_ctrl_nan_publish(struct wpa_supplicant *wpa_s, char *cmd,
+ char *buf, size_t buflen)
+{
+ char *token, *context = NULL;
+ int publish_id;
+ struct nan_publish_params params;
+ const char *service_name = NULL;
+ struct wpabuf *ssi = NULL;
+ int ret = -1;
+ enum nan_service_protocol_type srv_proto_type = 0;
+ int *freq_list = NULL;
+
+ os_memset(¶ms, 0, sizeof(params));
+ /* USD shall use both solicited and unsolicited transmissions */
+ params.unsolicited = true;
+ params.solicited = true;
+ /* USD shall require FSD without GAS */
+ params.fsd = true;
+ params.freq = NAN_USD_DEFAULT_FREQ;
+
+ while ((token = str_token(cmd, " ", &context))) {
+ if (os_strncmp(token, "service_name=", 13) == 0) {
+ service_name = token + 13;
+ continue;
+ }
+
+ if (os_strncmp(token, "ttl=", 4) == 0) {
+ params.ttl = atoi(token + 4);
+ continue;
+ }
+
+ if (os_strncmp(token, "freq=", 5) == 0) {
+ params.freq = atoi(token + 5);
+ continue;
+ }
+
+ if (os_strncmp(token, "freq_list=", 10) == 0) {
+ char *pos = token + 10;
+
+ if (os_strcmp(pos, "all") == 0) {
+ os_free(freq_list);
+ freq_list = wpas_nan_usd_all_freqs(wpa_s);
+ params.freq_list = freq_list;
+ continue;
+ }
+
+ while (pos && pos[0]) {
+ int_array_add_unique(&freq_list, atoi(pos));
+ pos = os_strchr(pos, ',');
+ if (pos)
+ pos++;
+ }
+
+ params.freq_list = freq_list;
+ continue;
+ }
+
+ if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
+ srv_proto_type = atoi(token + 15);
+ continue;
+ }
+
+ if (os_strncmp(token, "ssi=", 4) == 0) {
+ if (ssi)
+ goto fail;
+ ssi = wpabuf_parse_bin(token + 4);
+ if (!ssi)
+ goto fail;
+ continue;
+ }
+
+ if (os_strcmp(token, "solicited=0") == 0) {
+ params.solicited = false;
+ continue;
+ }
+
+ if (os_strcmp(token, "unsolicited=0") == 0) {
+ params.unsolicited = false;
+ continue;
+ }
+
+ if (os_strcmp(token, "fsd=0") == 0) {
+ params.fsd = false;
+ continue;
+ }
+
+ wpa_printf(MSG_INFO, "CTRL: Invalid NAN_PUBLISH parameter: %s",
+ token);
+ goto fail;
+ }
+
+ publish_id = wpas_nan_usd_publish(wpa_s, service_name, srv_proto_type,
+ ssi, ¶ms);
+ if (publish_id > 0)
+ ret = os_snprintf(buf, buflen, "%d", publish_id);
+fail:
+ wpabuf_free(ssi);
+ os_free(freq_list);
+ return ret;
+}
+
+
+static int wpas_ctrl_nan_cancel_publish(struct wpa_supplicant *wpa_s,
+ char *cmd)
+{
+ char *token, *context = NULL;
+ int publish_id = 0;
+
+ while ((token = str_token(cmd, " ", &context))) {
+ if (sscanf(token, "publish_id=%i", &publish_id) == 1)
+ continue;
+ wpa_printf(MSG_INFO,
+ "CTRL: Invalid NAN_CANCEL_PUBLISH parameter: %s",
+ token);
+ return -1;
+ }
+
+ if (publish_id <= 0) {
+ wpa_printf(MSG_INFO,
+ "CTRL: Invalid or missing NAN_CANCEL_PUBLISH publish_id");
+ return -1;
+ }
+
+ wpas_nan_usd_cancel_publish(wpa_s, publish_id);
+ return 0;
+}
+
+
+static int wpas_ctrl_nan_update_publish(struct wpa_supplicant *wpa_s,
+ char *cmd)
+{
+ char *token, *context = NULL;
+ int publish_id = 0;
+ struct wpabuf *ssi = NULL;
+ int ret = -1;
+
+ while ((token = str_token(cmd, " ", &context))) {
+ if (sscanf(token, "publish_id=%i", &publish_id) == 1)
+ continue;
+ if (os_strncmp(token, "ssi=", 4) == 0) {
+ if (ssi)
+ goto fail;
+ ssi = wpabuf_parse_bin(token + 4);
+ if (!ssi)
+ goto fail;
+ continue;
+ }
+ wpa_printf(MSG_INFO,
+ "CTRL: Invalid NAN_UPDATE_PUBLISH parameter: %s",
+ token);
+ goto fail;
+ }
+
+ if (publish_id <= 0) {
+ wpa_printf(MSG_INFO,
+ "CTRL: Invalid or missing NAN_UPDATE_PUBLISH publish_id");
+ goto fail;
+ }
+
+ ret = wpas_nan_usd_update_publish(wpa_s, publish_id, ssi);
+fail:
+ wpabuf_free(ssi);
+ return ret;
+}
+
+
+static int wpas_ctrl_nan_subscribe(struct wpa_supplicant *wpa_s, char *cmd,
+ char *buf, size_t buflen)
+{
+ char *token, *context = NULL;
+ int subscribe_id;
+ struct nan_subscribe_params params;
+ const char *service_name = NULL;
+ struct wpabuf *ssi = NULL;
+ int ret = -1;
+ enum nan_service_protocol_type srv_proto_type = 0;
+
+ os_memset(¶ms, 0, sizeof(params));
+ params.freq = NAN_USD_DEFAULT_FREQ;
+
+ while ((token = str_token(cmd, " ", &context))) {
+ if (os_strncmp(token, "service_name=", 13) == 0) {
+ service_name = token + 13;
+ continue;
+ }
+
+ if (os_strcmp(token, "active=1") == 0) {
+ params.active = true;
+ continue;
+ }
+
+ if (os_strncmp(token, "ttl=", 4) == 0) {
+ params.ttl = atoi(token + 4);
+ continue;
+ }
+
+ if (os_strncmp(token, "freq=", 5) == 0) {
+ params.freq = atoi(token + 5);
+ continue;
+ }
+
+ if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
+ srv_proto_type = atoi(token + 15);
+ continue;
+ }
+
+ if (os_strncmp(token, "ssi=", 4) == 0) {
+ if (ssi)
+ goto fail;
+ ssi = wpabuf_parse_bin(token + 4);
+ if (!ssi)
+ goto fail;
+ continue;
+ }
+
+ wpa_printf(MSG_INFO,
+ "CTRL: Invalid NAN_SUBSCRIBE parameter: %s",
+ token);
+ goto fail;
+ }
+
+ subscribe_id = wpas_nan_usd_subscribe(wpa_s, service_name,
+ srv_proto_type, ssi,
+ ¶ms);
+ if (subscribe_id > 0)
+ ret = os_snprintf(buf, buflen, "%d", subscribe_id);
+fail:
+ wpabuf_free(ssi);
+ return ret;
+}
+
+
+static int wpas_ctrl_nan_cancel_subscribe(struct wpa_supplicant *wpa_s,
+ char *cmd)
+{
+ char *token, *context = NULL;
+ int subscribe_id = 0;
+
+ while ((token = str_token(cmd, " ", &context))) {
+ if (sscanf(token, "subscribe_id=%i", &subscribe_id) == 1)
+ continue;
+ wpa_printf(MSG_INFO,
+ "CTRL: Invalid NAN_CANCEL_SUBSCRIBE parameter: %s",
+ token);
+ return -1;
+ }
+
+ if (subscribe_id <= 0) {
+ wpa_printf(MSG_INFO,
+ "CTRL: Invalid or missing NAN_CANCEL_SUBSCRIBE subscribe_id");
+ return -1;
+ }
+
+ wpas_nan_usd_cancel_subscribe(wpa_s, subscribe_id);
+ return 0;
+}
+
+
+static int wpas_ctrl_nan_transmit(struct wpa_supplicant *wpa_s, char *cmd)
+{
+ char *token, *context = NULL;
+ int handle = 0;
+ int req_instance_id = 0;
+ struct wpabuf *ssi = NULL;
+ u8 peer_addr[ETH_ALEN];
+ int ret = -1;
+
+ os_memset(peer_addr, 0, ETH_ALEN);
+
+ while ((token = str_token(cmd, " ", &context))) {
+ if (sscanf(token, "handle=%i", &handle) == 1)
+ continue;
+
+ if (sscanf(token, "req_instance_id=%i", &req_instance_id) == 1)
+ continue;
+
+ if (os_strncmp(token, "address=", 8) == 0) {
+ if (hwaddr_aton(token + 8, peer_addr) < 0)
+ return -1;
+ continue;
+ }
+
+ if (os_strncmp(token, "ssi=", 4) == 0) {
+ if (ssi)
+ goto fail;
+ ssi = wpabuf_parse_bin(token + 4);
+ if (!ssi)
+ goto fail;
+ continue;
+ }
+
+ wpa_printf(MSG_INFO,
+ "CTRL: Invalid NAN_TRANSMIT parameter: %s",
+ token);
+ goto fail;
+ }
+
+ if (handle <= 0) {
+ wpa_printf(MSG_INFO,
+ "CTRL: Invalid or missing NAN_TRANSMIT handle");
+ goto fail;
+ }
+
+ if (is_zero_ether_addr(peer_addr)) {
+ wpa_printf(MSG_INFO,
+ "CTRL: Invalid or missing NAN_TRANSMIT address");
+ goto fail;
+ }
+
+ ret = wpas_nan_usd_transmit(wpa_s, handle, ssi, NULL, peer_addr,
+ req_instance_id);
+fail:
+ wpabuf_free(ssi);
+ return ret;
+}
+
+#endif /* CONFIG_NAN_USD */
+
+
char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
char *buf, size_t *resp_len)
{
@@ -12792,6 +13155,7 @@
reply_len = wpa_supplicant_ctrl_iface_tdls_link_status(
wpa_s, buf + 17, reply, reply_size);
#endif /* CONFIG_TDLS */
+#ifndef CONFIG_NO_WMM_AC
} else if (os_strcmp(buf, "WMM_AC_STATUS") == 0) {
reply_len = wpas_wmm_ac_status(wpa_s, reply, reply_size);
} else if (os_strncmp(buf, "WMM_AC_ADDTS ", 13) == 0) {
@@ -12800,6 +13164,7 @@
} else if (os_strncmp(buf, "WMM_AC_DELTS ", 13) == 0) {
if (wmm_ac_ctrl_delts(wpa_s, buf + 13))
reply_len = -1;
+#endif /* CONFIG_NO_WMM_AC */
} else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
reply_size);
@@ -12886,21 +13251,27 @@
if (wpas_ctrl_iface_data_test_frame(wpa_s, buf + 16) < 0)
reply_len = -1;
} else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
- if (wpas_ctrl_test_alloc_fail(wpa_s, buf + 16) < 0)
+ if (testing_set_fail_pattern(true, buf + 16) < 0)
reply_len = -1;
} else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
- reply_len = wpas_ctrl_get_alloc_fail(wpa_s, reply, reply_size);
+ reply_len = testing_get_fail_pattern(true, reply, reply_size);
} else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
- if (wpas_ctrl_test_fail(wpa_s, buf + 10) < 0)
+ if (testing_set_fail_pattern(false, buf + 10) < 0)
reply_len = -1;
} else if (os_strcmp(buf, "GET_FAIL") == 0) {
- reply_len = wpas_ctrl_get_fail(wpa_s, reply, reply_size);
+ reply_len = testing_get_fail_pattern(false, reply, reply_size);
} else if (os_strncmp(buf, "EVENT_TEST ", 11) == 0) {
if (wpas_ctrl_event_test(wpa_s, buf + 11) < 0)
reply_len = -1;
} else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) {
if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0)
reply_len = -1;
+ } else if (os_strncmp(buf, "TEST_EAPOL_M2_ELEMS ", 20) == 0) {
+ if (wpas_ctrl_test_eapol_m2_elems(wpa_s, buf + 20) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "TEST_EAPOL_M4_ELEMS ", 20) == 0) {
+ if (wpas_ctrl_test_eapol_m4_elems(wpa_s, buf + 20) < 0)
+ reply_len = -1;
} else if (os_strcmp(buf, "RESET_PN") == 0) {
if (wpas_ctrl_reset_pn(wpa_s) < 0)
reply_len = -1;
@@ -12939,9 +13310,11 @@
} else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) {
if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0)
reply_len = -1;
+#ifndef CONFIG_NO_RRM
} else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) {
if (wpas_ctrl_iface_send_neighbor_rep(wpa_s, buf + 20))
reply_len = -1;
+#endif /* CONFIG_NO_RRM */
} else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
wpas_ctrl_iface_erp_flush(wpa_s);
} else if (os_strncmp(buf, "MAC_RAND_SCAN ", 14) == 0) {
@@ -13114,9 +13487,26 @@
reply_len = -1;
#endif /* CONFIG_DPP3 */
#endif /* CONFIG_DPP */
- } else if (os_strncmp(buf, "MSCS ", 5) == 0) {
- if (wpas_ctrl_iface_configure_mscs(wpa_s, buf + 5))
+#ifdef CONFIG_NAN_USD
+ } else if (os_strncmp(buf, "NAN_PUBLISH ", 12) == 0) {
+ reply_len = wpas_ctrl_nan_publish(wpa_s, buf + 12, reply,
+ reply_size);
+ } else if (os_strncmp(buf, "NAN_CANCEL_PUBLISH ", 19) == 0) {
+ if (wpas_ctrl_nan_cancel_publish(wpa_s, buf + 19) < 0)
reply_len = -1;
+ } else if (os_strncmp(buf, "NAN_UPDATE_PUBLISH ", 19) == 0) {
+ if (wpas_ctrl_nan_update_publish(wpa_s, buf + 19) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "NAN_SUBSCRIBE ", 14) == 0) {
+ reply_len = wpas_ctrl_nan_subscribe(wpa_s, buf + 14, reply,
+ reply_size);
+ } else if (os_strncmp(buf, "NAN_CANCEL_SUBSCRIBE ", 21) == 0) {
+ if (wpas_ctrl_nan_cancel_subscribe(wpa_s, buf + 21) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "NAN_TRANSMIT ", 13) == 0) {
+ if (wpas_ctrl_nan_transmit(wpa_s, buf + 13) < 0)
+ reply_len = -1;
+#endif /* CONFIG_NAN_USD */
#ifdef CONFIG_PASN
} else if (os_strncmp(buf, "PASN_START ", 11) == 0) {
if (wpas_ctrl_iface_pasn_start(wpa_s, buf + 11) < 0)
@@ -13128,7 +13518,16 @@
} else if (os_strncmp(buf, "PASN_DEAUTH ", 12) == 0) {
if (wpas_ctrl_iface_pasn_deauthenticate(wpa_s, buf + 12) < 0)
reply_len = -1;
+#ifdef CONFIG_TESTING_OPTIONS
+ } else if (os_strncmp(buf, "PASN_DRIVER ", 12) == 0) {
+ if (wpas_ctrl_iface_pasn_driver(wpa_s, buf + 12) < 0)
+ reply_len = -1;
+#endif /* CONFIG_TESTING_OPTIONS */
#endif /* CONFIG_PASN */
+#ifndef CONFIG_NO_ROBUST_AV
+ } else if (os_strncmp(buf, "MSCS ", 5) == 0) {
+ if (wpas_ctrl_iface_configure_mscs(wpa_s, buf + 5))
+ reply_len = -1;
} else if (os_strncmp(buf, "SCS ", 4) == 0) {
if (wpas_ctrl_iface_configure_scs(wpa_s, buf + 4))
reply_len = -1;
@@ -13138,6 +13537,7 @@
} else if (os_strncmp(buf, "DSCP_QUERY ", 11) == 0) {
if (wpas_ctrl_iface_send_dscp_query(wpa_s, buf + 11))
reply_len = -1;
+#endif /* CONFIG_NO_ROBUST_AV */
} else if (os_strcmp(buf, "MLO_STATUS") == 0) {
reply_len = wpas_ctrl_iface_mlo_status(wpa_s, reply,
reply_size);
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 8fc29b3..00b38ed 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -4304,6 +4304,14 @@
}
},
#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_HS20
+ { "HS20TermsAndConditions", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ {
+ { "url", "s", ARG_OUT },
+ END_ARGS
+ }
+ },
+#endif /* CONFIG_HS20 */
{ NULL, NULL, { END_ARGS } }
};
@@ -5142,3 +5150,39 @@
}
#endif /* CONFIG_P2P */
+
+
+#ifdef CONFIG_HS20
+/**
+ * wpas_dbus_signal_hs20_t_c_acceptance - Signals a terms and conditions was
+ * received.
+ *
+ * @wpa_s: %wpa_supplicant network interface data
+ * @url: URL of the terms and conditions acceptance page.
+ */
+void wpas_dbus_signal_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
+ const char *url)
+{
+ struct wpas_dbus_priv *iface;
+ DBusMessage *msg;
+
+ iface = wpa_s->global->dbus;
+
+ /* Do nothing if the control interface is not turned on */
+ if (!iface || !wpa_s->dbus_new_path)
+ return;
+
+ msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+ WPAS_DBUS_NEW_IFACE_INTERFACE,
+ "HS20TermsAndConditions");
+ if (!msg)
+ return;
+
+ if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &url,
+ DBUS_TYPE_INVALID))
+ dbus_connection_send(iface->con, msg, NULL);
+ else
+ wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+ dbus_message_unref(msg);
+}
+#endif /* CONFIG_HS20 */
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index 5c5d855..b653f10 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -279,6 +279,8 @@
int bh, int bss_load,
int conn_capab);
void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s);
+void wpas_dbus_signal_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
+ const char *url);
#else /* CONFIG_CTRL_IFACE_DBUS_NEW */
@@ -650,6 +652,12 @@
{
}
+static inline
+void wpas_dbus_signal_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
+ const char *url)
+{
+}
+
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
#endif /* CTRL_IFACE_DBUS_H_NEW */
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index a178d87..16b2caa 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -14,6 +14,7 @@
#include "../wpa_supplicant_i.h"
#include "../wps_supplicant.h"
#include "../notify.h"
+#include "../bss.h"
#include "dbus_new_helpers.h"
#include "dbus_new.h"
#include "dbus_new_handlers.h"
@@ -360,6 +361,12 @@
unsigned int group_id = 0;
struct wpa_ssid *ssid;
u8 go_bssid_buf[ETH_ALEN], *go_bssid = NULL;
+ 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;
+ int edmg = wpa_s->conf->p2p_go_edmg;
+ int max_oper_chwidth, chwidth = 0, freq2 = 0;
dbus_message_iter_init(message, &iter);
@@ -392,6 +399,28 @@
if (hwaddr_aton(entry.str_value, go_bssid_buf))
goto inv_args_clear;
go_bssid = go_bssid_buf;
+ } else if (os_strcmp(entry.key, "ht40") == 0 &&
+ entry.type == DBUS_TYPE_BOOLEAN) {
+ ht40 = entry.bool_value;
+ } else if (os_strcmp(entry.key, "vht") == 0 &&
+ entry.type == DBUS_TYPE_BOOLEAN) {
+ vht = entry.bool_value;
+ ht40 |= vht;
+ } else if (os_strcmp(entry.key, "he") == 0 &&
+ entry.type == DBUS_TYPE_BOOLEAN) {
+ he = entry.bool_value;
+ } else if (os_strcmp(entry.key, "edmg") == 0 &&
+ entry.type == DBUS_TYPE_BOOLEAN) {
+ edmg = entry.bool_value;
+ } else if (os_strcmp(entry.key, "allow_6ghz") == 0 &&
+ entry.type == DBUS_TYPE_BOOLEAN) {
+ allow_6ghz = entry.bool_value;
+ } else if (os_strcmp(entry.key, "freq2") == 0 &&
+ entry.type == DBUS_TYPE_INT32) {
+ freq2 = entry.int32_value;
+ } else if (os_strcmp(entry.key, "max_oper_chwidth") == 0 &&
+ entry.type == DBUS_TYPE_INT32) {
+ chwidth = entry.int32_value;
} else {
goto inv_args_clear;
}
@@ -399,6 +428,13 @@
wpa_dbus_dict_entry_clear(&entry);
}
+ max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
+ if (max_oper_chwidth < 0)
+ goto inv_args;
+
+ if (allow_6ghz && chwidth == 40)
+ max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ;
+
wpa_s = wpa_s->global->p2p_init_wpa_s;
if (!wpa_s) {
reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
@@ -437,17 +473,19 @@
if (ssid == NULL || ssid->disabled != 2)
goto inv_args;
- if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
- 0, 0, 0, 0, NULL, 0, 0,
- false, retry_limit,
- go_bssid)) {
+ if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0,
+ freq2, ht40, vht,
+ max_oper_chwidth, he, edmg,
+ NULL, 0, 0, allow_6ghz,
+ retry_limit, go_bssid)) {
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, false))
+ } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, freq2,
+ ht40, vht, max_oper_chwidth, he, edmg,
+ allow_6ghz))
goto inv_args;
out:
@@ -2427,9 +2465,9 @@
u8 *p_bssid;
if (role == WPAS_P2P_ROLE_CLIENT) {
- if (wpa_s->current_ssid == NULL)
+ if (!wpa_s->current_bss)
return FALSE;
- p_bssid = wpa_s->current_ssid->bssid;
+ p_bssid = wpa_s->current_bss->bssid;
} else {
if (wpa_s->ap_iface == NULL)
return FALSE;
@@ -2451,9 +2489,9 @@
u8 role = wpas_get_p2p_role(wpa_s);
if (role == WPAS_P2P_ROLE_CLIENT) {
- if (wpa_s->go_params == NULL)
+ if (!wpa_s->current_bss)
return FALSE;
- op_freq = wpa_s->go_params->freq;
+ op_freq = wpa_s->current_bss->freq;
} else {
if (wpa_s->ap_iface == NULL)
return FALSE;
diff --git a/wpa_supplicant/dbus/dbus_new_helpers.c b/wpa_supplicant/dbus/dbus_new_helpers.c
index 7fb0669..28f1aa4 100644
--- a/wpa_supplicant/dbus/dbus_new_helpers.c
+++ b/wpa_supplicant/dbus/dbus_new_helpers.c
@@ -671,20 +671,27 @@
&interface) ||
/* Changed properties dict */
!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
- "{sv}", &dict_iter) ||
- !put_changed_properties(obj_dsc, interface, &dict_iter, 0) ||
- !dbus_message_iter_close_container(&signal_iter, &dict_iter) ||
+ "{sv}", &dict_iter))
+ goto fail;
+ if (!put_changed_properties(obj_dsc, interface, &dict_iter, 0)) {
+ dbus_message_iter_close_container(&signal_iter, &dict_iter);
+ goto fail;
+ }
+ if (!dbus_message_iter_close_container(&signal_iter, &dict_iter) ||
/* Invalidated properties array (empty) */
!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
"s", &dict_iter) ||
- !dbus_message_iter_close_container(&signal_iter, &dict_iter)) {
- wpa_printf(MSG_DEBUG, "dbus: %s: Failed to construct signal",
- __func__);
- } else {
- dbus_connection_send(con, msg, NULL);
- }
+ !dbus_message_iter_close_container(&signal_iter, &dict_iter))
+ goto fail;
+ dbus_connection_send(con, msg, NULL);
+
+out:
dbus_message_unref(msg);
+ return;
+fail:
+ wpa_printf(MSG_DEBUG, "dbus: %s: Failed to construct signal", __func__);
+ goto out;
}
@@ -702,16 +709,23 @@
dbus_message_iter_init_append(msg, &signal_iter);
if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
- "{sv}", &dict_iter) ||
- !put_changed_properties(obj_dsc, interface, &dict_iter, 1) ||
- !dbus_message_iter_close_container(&signal_iter, &dict_iter)) {
- wpa_printf(MSG_DEBUG, "dbus: %s: Failed to construct signal",
- __func__);
- } else {
- dbus_connection_send(con, msg, NULL);
+ "{sv}", &dict_iter))
+ goto fail;
+ if (!put_changed_properties(obj_dsc, interface, &dict_iter, 1)) {
+ dbus_message_iter_close_container(&signal_iter, &dict_iter);
+ goto fail;
}
+ if (!dbus_message_iter_close_container(&signal_iter, &dict_iter))
+ goto fail;
+ dbus_connection_send(con, msg, NULL);
+
+out:
dbus_message_unref(msg);
+ return;
+fail:
+ wpa_printf(MSG_DEBUG, "dbus: %s: Failed to construct signal", __func__);
+ goto out;
}
diff --git a/wpa_supplicant/dbus/dbus_new_introspect.c b/wpa_supplicant/dbus/dbus_new_introspect.c
index 6c721bf..a8c0d28 100644
--- a/wpa_supplicant/dbus/dbus_new_introspect.c
+++ b/wpa_supplicant/dbus/dbus_new_introspect.c
@@ -38,7 +38,7 @@
if (!iface)
return NULL;
iface->dbus_interface = os_strdup(dbus_interface);
- iface->xml = wpabuf_alloc(15000);
+ iface->xml = wpabuf_alloc(16000);
if (iface->dbus_interface == NULL || iface->xml == NULL) {
os_free(iface->dbus_interface);
wpabuf_free(iface->xml);
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index 1ae5a9f..c0192e0 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -677,3 +677,17 @@
# production use.
#CONFIG_PASN=y
+# Disable support for Radio Measurement (IEEE 802.11k) and supported operating
+# class indication. Removing these is not recommended since they can help the
+# AP manage the network and STA steering.
+#CONFIG_NO_RRM=y
+
+# Disable support for Robust AV streaming for consumer and enterprise Wi-Fi
+# applications; IEEE Std 802.11-2020, 4.3.24; SCS, MSCS, QoS Management
+#CONFIG_NO_ROBUST_AV=y
+
+# Disable support for WMM admission control
+#CONFIG_NO_WMM_AC=y
+
+# Wi-Fi Aware unsynchronized service discovery (NAN USD)
+#CONFIG_NAN_USD=y
diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c
index 4f5be0a..801e698 100644
--- a/wpa_supplicant/dpp_supplicant.c
+++ b/wpa_supplicant/dpp_supplicant.c
@@ -1800,7 +1800,7 @@
wpa_s->dpp_gas_dialog_token = -1;
if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
- os_memcmp(addr, auth->peer_mac_addr, ETH_ALEN) != 0) {
+ !ether_addr_equal(addr, auth->peer_mac_addr)) {
wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
return;
}
@@ -1935,7 +1935,11 @@
offchannel_send_action_done(wpa_s);
wpas_dpp_listen_stop(wpa_s);
+#ifdef CONFIG_NO_RRM
+ supp_op_classes = NULL;
+#else /* CONFIG_NO_RRM */
supp_op_classes = wpas_supp_op_classes(wpa_s);
+#endif /* CONFIG_NO_RRM */
buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
wpa_s->dpp_netrole,
wpa_s->conf->dpp_mud_url,
@@ -2016,7 +2020,7 @@
}
if (!is_zero_ether_addr(auth->peer_mac_addr) &&
- os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
+ !ether_addr_equal(src, auth->peer_mac_addr)) {
wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
return;
@@ -2071,7 +2075,7 @@
return;
}
- if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
+ if (!ether_addr_equal(src, auth->peer_mac_addr)) {
wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
return;
@@ -2175,7 +2179,7 @@
if (!auth || !auth->waiting_conf_result) {
if (auth &&
- os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) == 0 &&
+ ether_addr_equal(src, auth->peer_mac_addr) &&
gas_server_response_sent(wpa_s->gas_server,
auth->gas_server_ctx)) {
/* This could happen if the TX status event gets delayed
@@ -2192,7 +2196,7 @@
}
}
- if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
+ if (!ether_addr_equal(src, auth->peer_mac_addr)) {
wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
return;
@@ -2608,7 +2612,7 @@
return;
}
- if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
+ if (!ether_addr_equal(src, auth->peer_mac_addr)) {
wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
return;
@@ -2652,7 +2656,7 @@
return;
}
- if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
+ if (!ether_addr_equal(src, auth->peer_mac_addr)) {
wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
return;
@@ -2690,7 +2694,7 @@
wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
MAC2STR(src));
if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
- os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
+ !ether_addr_equal(src, wpa_s->dpp_intro_bssid)) {
wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
MACSTR " - drop", MAC2STR(src));
return;
@@ -3854,7 +3858,7 @@
wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction Notify from "
MACSTR, MAC2STR(src));
if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
- os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
+ !ether_addr_equal(src, wpa_s->dpp_intro_bssid)) {
wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
MACSTR " - drop", MAC2STR(src));
return;
@@ -4145,7 +4149,7 @@
wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
MAC2STR(sa));
if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
- os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
+ !ether_addr_equal(sa, auth->peer_mac_addr)) {
wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
return NULL;
}
@@ -4159,6 +4163,13 @@
* exchange. */
dpp_notify_auth_success(auth, 1);
wpa_s->dpp_auth_ok_on_ack = 0;
+#ifdef CONFIG_TESTING_OPTIONS
+ if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
+ wpa_printf(MSG_INFO,
+ "DPP: TESTING - stop at Authentication Confirm");
+ return NULL;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
}
wpa_hexdump(MSG_DEBUG,
@@ -5692,6 +5703,8 @@
if (wpa_s->dpp_pb_bi) {
char id[20];
+ if (wpa_s->dpp_pb_bi == wpa_s->dpp_pkex_bi)
+ wpa_s->dpp_pkex_bi = NULL;
os_snprintf(id, sizeof(id), "%u", wpa_s->dpp_pb_bi->id);
dpp_bootstrap_remove(wpa_s->dpp, id);
wpa_s->dpp_pb_bi = NULL;
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index dcf5764..9a4c235 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -1155,8 +1155,10 @@
{
struct secure_ranging_params params;
+ /* Configure secure ranging context only to the drivers that support it.
+ */
if (!wpa_s->driver->set_secure_ranging_ctx)
- return -1;
+ return 0;
os_memset(¶ms, 0, sizeof(params));
params.action = action;
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index f386119..bc45579 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -50,6 +50,7 @@
#include "mesh.h"
#include "mesh_mpm.h"
#include "wmm_ac.h"
+#include "nan_usd.h"
#include "dpp_supplicant.h"
#include "rsn_supp/wpa_i.h"
@@ -383,8 +384,13 @@
wpa_s->key_mgmt = 0;
wpa_s->allowed_key_mgmts = 0;
+#ifndef CONFIG_NO_RRM
wpas_rrm_reset(wpa_s);
+#endif /* CONFIG_NO_RRM */
wpa_s->wnmsleep_used = 0;
+#ifdef CONFIG_WNM
+ wpa_s->wnm_mode = 0;
+#endif /* CONFIG_WNM */
wnm_clear_coloc_intf_reporting(wpa_s);
wpa_s->disable_mbo_oce = 0;
@@ -759,15 +765,33 @@
return 0;
}
+ wpa_ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
+
if (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED &&
(!(ssid->key_mgmt & WPA_KEY_MGMT_OWE) || ssid->owe_only)) {
+#ifdef CONFIG_OWE
+ if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) && ssid->owe_only &&
+ !wpa_ie && !rsn_ie &&
+ wpa_s->owe_transition_select &&
+ wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE) &&
+ ssid->owe_transition_bss_select_count + 1 <=
+ MAX_OWE_TRANSITION_BSS_SELECT_COUNT) {
+ ssid->owe_transition_bss_select_count++;
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip OWE open BSS (selection count %d does not exceed %d)",
+ ssid->owe_transition_bss_select_count,
+ MAX_OWE_TRANSITION_BSS_SELECT_COUNT);
+ wpa_s->owe_transition_search = 1;
+ return 0;
+ }
+#endif /* CONFIG_OWE */
if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG,
" skip - MFP Required but network not MFP Capable");
return 0;
}
- wpa_ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
while ((ssid->proto & WPA_PROTO_WPA) && wpa_ie) {
proto_match++;
@@ -1136,7 +1160,7 @@
{
u16 removed_links;
- if (wpa_bss_parse_basic_ml_element(wpa_s, bss, NULL, NULL))
+ if (wpa_bss_parse_basic_ml_element(wpa_s, bss, NULL, NULL, NULL, NULL))
return true;
if (bss->n_mld_links == 0)
@@ -1285,7 +1309,7 @@
#endif /* CONFIG_WPS */
if (ssid->bssid_set && ssid->ssid_len == 0 &&
- os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) == 0)
+ ether_addr_equal(bss->bssid, ssid->bssid))
check_ssid = false;
if (check_ssid &&
@@ -1297,7 +1321,7 @@
}
if (ssid->bssid_set &&
- os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) {
+ !ether_addr_equal(bss->bssid, ssid->bssid)) {
if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID mismatch");
return false;
@@ -1466,7 +1490,7 @@
}
if (p2p_parse_dev_addr_in_p2p_ie(p2p_ie, dev_addr) < 0 ||
- os_memcmp(dev_addr, ssid->go_p2p_dev_addr, ETH_ALEN) != 0) {
+ !ether_addr_equal(dev_addr, ssid->go_p2p_dev_addr)) {
if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG,
" skip - no matching GO P2P Device Address in P2P element");
@@ -1673,6 +1697,14 @@
return NULL;
}
+#ifdef CONFIG_WNM
+ if (wnm_is_bss_excluded(wpa_s, bss)) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID excluded");
+ return NULL;
+ }
+#endif /* CONFIG_WNM */
+
for (ssid = group; ssid; ssid = only_first_ssid ? NULL : ssid->pnext) {
if (wpa_scan_res_ok(wpa_s, ssid, match_ssid, match_ssid_len,
bss, bssid_ignore_count, debug_print))
@@ -1857,14 +1889,16 @@
{
int *freqs;
u16 missing_links = 0, removed_links;
+ u8 ap_mld_id;
if (!((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)))
return 0;
- /* Try to resolve any missing link information */
if (wpa_bss_parse_basic_ml_element(wpa_s, selected, NULL,
- &missing_links) || !missing_links)
+ &missing_links, ssid,
+ &ap_mld_id) ||
+ !missing_links)
return 0;
removed_links = wpa_bss_parse_reconf_ml_element(wpa_s, selected);
@@ -1895,7 +1929,36 @@
wpa_s->manual_scan_freqs = freqs;
os_memcpy(wpa_s->ml_probe_bssid, selected->bssid, ETH_ALEN);
- wpa_s->ml_probe_mld_id = -1;
+
+ /*
+ * In case the ML probe request is intended to retrieve information from
+ * the transmitted BSS, the AP MLD ID should be included and should be
+ * set to zero.
+ * In case the ML probe requested is intended to retrieve information
+ * from a non-transmitted BSS, the AP MLD ID should not be included.
+ */
+ if (ap_mld_id)
+ wpa_s->ml_probe_mld_id = -1;
+ else
+ wpa_s->ml_probe_mld_id = 0;
+
+ if (ssid && ssid->ssid_len) {
+ os_free(wpa_s->ssids_from_scan_req);
+ wpa_s->num_ssids_from_scan_req = 0;
+
+ wpa_s->ssids_from_scan_req =
+ os_zalloc(sizeof(struct wpa_ssid_value));
+ if (wpa_s->ssids_from_scan_req) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: ML probe: With direct SSID");
+
+ wpa_s->num_ssids_from_scan_req = 1;
+ wpa_s->ssids_from_scan_req[0].ssid_len = ssid->ssid_len;
+ os_memcpy(wpa_s->ssids_from_scan_req[0].ssid,
+ ssid->ssid, ssid->ssid_len);
+ }
+ }
+
wpa_s->ml_probe_links = missing_links;
wpa_s->normal_scans = 0;
@@ -1952,12 +2015,11 @@
* the selected BSSID, do not trigger new attempt.
*/
if (wpa_s->reassociate ||
- (os_memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0 &&
+ (!ether_addr_equal(selected->bssid, wpa_s->bssid) &&
((wpa_s->wpa_state != WPA_ASSOCIATING &&
wpa_s->wpa_state != WPA_AUTHENTICATING) ||
(!is_zero_ether_addr(wpa_s->pending_bssid) &&
- os_memcmp(selected->bssid, wpa_s->pending_bssid, ETH_ALEN) !=
- 0) ||
+ !ether_addr_equal(selected->bssid, wpa_s->pending_bssid)) ||
(is_zero_ether_addr(wpa_s->pending_bssid) &&
ssid != wpa_s->current_ssid)))) {
if (wpa_supplicant_scard_init(wpa_s, ssid)) {
@@ -2070,11 +2132,22 @@
}
+static int wpas_evaluate_band_score(int frequency)
+{
+ if (is_6ghz_freq(frequency))
+ return 2;
+ if (IS_5GHZ(frequency))
+ return 1;
+ return 0;
+}
+
+
int wpa_supplicant_need_to_roam_within_ess(struct wpa_supplicant *wpa_s,
struct wpa_bss *current_bss,
struct wpa_bss *selected)
{
int min_diff, diff;
+ int cur_band_score, sel_band_score;
int to_5ghz, to_6ghz;
int cur_level, sel_level;
unsigned int cur_est, sel_est;
@@ -2100,8 +2173,7 @@
selected->snr, selected->est_throughput);
if (wpa_s->current_ssid->bssid_set &&
- os_memcmp(selected->bssid, wpa_s->current_ssid->bssid, ETH_ALEN) ==
- 0) {
+ ether_addr_equal(selected->bssid, wpa_s->current_ssid->bssid)) {
wpa_dbg(wpa_s, MSG_DEBUG, "Allow reassociation - selected BSS "
"has preferred BSSID");
return 1;
@@ -2221,9 +2293,11 @@
else if (sel_est > cur_est)
min_diff--;
- if (to_5ghz)
- min_diff -= 2;
- if (to_6ghz)
+ cur_band_score = wpas_evaluate_band_score(current_bss->freq);
+ sel_band_score = wpas_evaluate_band_score(selected->freq);
+ min_diff += (cur_band_score - sel_band_score) * 2;
+ if (wpa_s->signal_threshold && cur_level <= wpa_s->signal_threshold &&
+ sel_level > wpa_s->signal_threshold)
min_diff -= 2;
diff = sel_level - cur_level;
if (diff < min_diff) {
@@ -2256,6 +2330,7 @@
struct wpa_ssid *ssid)
{
struct wpa_bss *current_bss = NULL;
+ const u8 *bssid;
if (wpa_s->reassociate)
return 1; /* explicit request to reassociate */
@@ -2269,12 +2344,17 @@
if (wpas_driver_bss_selection(wpa_s))
return 0; /* Driver-based roaming */
+ if (wpa_s->valid_links)
+ bssid = wpa_s->links[wpa_s->mlo_assoc_link_id].bssid;
+ else
+ bssid = wpa_s->bssid;
+
if (wpa_s->current_ssid->ssid)
- current_bss = wpa_bss_get(wpa_s, wpa_s->bssid,
+ current_bss = wpa_bss_get(wpa_s, bssid,
wpa_s->current_ssid->ssid,
wpa_s->current_ssid->ssid_len);
if (!current_bss)
- current_bss = wpa_bss_get_bssid(wpa_s, wpa_s->bssid);
+ current_bss = wpa_bss_get_bssid(wpa_s, bssid);
if (!current_bss)
return 1; /* current BSS not seen in scan results */
@@ -2424,9 +2504,11 @@
if (sme_proc_obss_scan(wpa_s) > 0)
goto scan_work_done;
+#ifndef CONFIG_NO_RRM
if (own_request && data &&
wpas_beacon_rep_scan_process(wpa_s, scan_res, &data->scan_info) > 0)
goto scan_work_done;
+#endif /* CONFIG_NO_RRM */
if (ml_link_probe_scan(wpa_s))
goto scan_work_done;
@@ -3586,10 +3668,12 @@
data->assoc_info.resp_ies_len);
#endif /* CONFIG_IEEE80211R */
+#ifndef CONFIG_NO_ROBUST_AV
if (bssid_known)
wpas_handle_assoc_resp_mscs(wpa_s, bssid,
data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len);
+#endif /* CONFIG_NO_ROBUST_AV */
/* WPA/RSN IE from Beacon/ProbeResp */
p = data->assoc_info.beacon_ies;
@@ -3644,8 +3728,10 @@
wpa_s->assoc_freq = data->assoc_info.freq;
+#ifndef CONFIG_NO_ROBUST_AV
wpas_handle_assoc_resp_qos_mgmt(wpa_s, data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len);
+#endif /* CONFIG_NO_ROBUST_AV */
return 0;
}
@@ -3717,6 +3803,261 @@
}
+static unsigned int wpas_ml_parse_assoc(struct wpa_supplicant *wpa_s,
+ struct ieee802_11_elems *elems,
+ struct ml_sta_link_info *ml_info)
+{
+ struct wpabuf *mlbuf;
+ struct ieee80211_eht_ml *ml;
+ size_t ml_len;
+ struct eht_ml_basic_common_info *common_info;
+ const u8 *pos;
+ u16 eml_capa = 0, mld_capa = 0;
+ const u16 control =
+ host_to_le16(MULTI_LINK_CONTROL_TYPE_BASIC |
+ BASIC_MULTI_LINK_CTRL_PRES_LINK_ID |
+ BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT);
+ u8 expected_common_info_len = 9;
+ unsigned int i = 0;
+ u16 ml_control;
+
+ if (!wpa_s->valid_links || !elems->basic_mle || !elems->basic_mle_len)
+ return 0;
+
+ mlbuf = ieee802_11_defrag(elems->basic_mle, elems->basic_mle_len, true);
+ if (!mlbuf)
+ return 0;
+
+ ml = (struct ieee80211_eht_ml *) wpabuf_head(mlbuf);
+ ml_len = wpabuf_len(mlbuf);
+ if (ml_len < sizeof(*ml))
+ goto out;
+
+ os_memset(ml_info, 0, sizeof(*ml_info) * MAX_NUM_MLD_LINKS);
+
+ ml_control = le_to_host16(ml->ml_control);
+
+ if ((ml_control & control) != control) {
+ wpa_printf(MSG_DEBUG, "MLD: Invalid presence BM=0x%x",
+ ml_control);
+ goto out;
+ }
+
+ if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA) {
+ wpa_printf(MSG_DEBUG, "MLD: EML capabilities included");
+ expected_common_info_len += 2;
+ }
+
+ if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA) {
+ wpa_printf(MSG_DEBUG, "MLD: MLD capabilities included");
+ expected_common_info_len += 2;
+ }
+
+ if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MSD_INFO) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: Unexpected: medium sync delay info present");
+ expected_common_info_len += 2;
+ }
+
+ if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_AP_MLD_ID) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: Unexpected: MLD ID present");
+ expected_common_info_len++;
+ }
+
+ if (sizeof(*ml) + expected_common_info_len > ml_len) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: Not enough bytes for common info. ml_len=%zu",
+ ml_len);
+ goto out;
+ }
+
+ common_info = (struct eht_ml_basic_common_info *) ml->variable;
+ if (common_info->len != expected_common_info_len) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: Invalid common info len=%u. expected=%u",
+ common_info->len, expected_common_info_len);
+ goto out;
+ }
+
+ wpa_printf(MSG_DEBUG, "MLD: address: " MACSTR,
+ MAC2STR(common_info->mld_addr));
+
+ if (!ether_addr_equal(wpa_s->ap_mld_addr, common_info->mld_addr)) {
+ wpa_printf(MSG_DEBUG, "MLD: Mismatching MLD address (expected "
+ MACSTR ")", MAC2STR(wpa_s->ap_mld_addr));
+ goto out;
+ }
+
+ pos = common_info->variable;
+
+ /* Store the information for the association link */
+ ml_info[i].link_id = *pos;
+ pos++;
+
+ /* Skip the BSS Parameters Change Count */
+ pos++;
+
+ /* Skip the Medium Synchronization Delay Information if present */
+ if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MSD_INFO)
+ pos += 2;
+
+ if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA) {
+ eml_capa = WPA_GET_LE16(pos);
+ pos += 2;
+ }
+
+ if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA) {
+ mld_capa = WPA_GET_LE16(pos);
+ pos += 2;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "MLD: link_id=%u, eml=0x%x, mld=0x%x",
+ ml_info[i].link_id, eml_capa, mld_capa);
+
+ i++;
+
+ pos = ((u8 *) common_info) + common_info->len;
+ ml_len -= sizeof(*ml) + common_info->len;
+ while (ml_len > 2 && i < MAX_NUM_MLD_LINKS) {
+ u8 sub_elem_len = pos[1];
+ u8 sta_info_len;
+ u8 nstr_bitmap_len = 0;
+ u16 ctrl;
+ const u8 *end;
+
+ wpa_printf(MSG_DEBUG, "MLD: Subelement len=%u", sub_elem_len);
+
+ if (sub_elem_len > ml_len - 2) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: Invalid link info len: %u > %zu",
+ 2 + sub_elem_len, ml_len);
+ goto out;
+ }
+
+ switch (*pos) {
+ case EHT_ML_SUB_ELEM_PER_STA_PROFILE:
+ break;
+ case EHT_ML_SUB_ELEM_FRAGMENT:
+ case EHT_ML_SUB_ELEM_VENDOR:
+ wpa_printf(MSG_DEBUG,
+ "MLD: Skip subelement id=%u, len=%u",
+ *pos, sub_elem_len);
+ pos += 2 + sub_elem_len;
+ ml_len -= 2 + sub_elem_len;
+ continue;
+ default:
+ wpa_printf(MSG_DEBUG, "MLD: Unknown subelement ID=%u",
+ *pos);
+ goto out;
+ }
+
+ end = pos + 2 + sub_elem_len;
+
+ /* Skip the subelement ID and the length */
+ pos += 2;
+ ml_len -= 2;
+
+ if (end - pos < 2)
+ goto out;
+
+ /* Get the station control field */
+ ctrl = WPA_GET_LE16(pos);
+
+ pos += 2;
+ ml_len -= 2;
+
+ if (!(ctrl & EHT_PER_STA_CTRL_COMPLETE_PROFILE_MSK)) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: Per STA complete profile expected");
+ goto out;
+ }
+
+ if (!(ctrl & EHT_PER_STA_CTRL_MAC_ADDR_PRESENT_MSK)) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: Per STA MAC address not present");
+ goto out;
+ }
+
+ if (!(ctrl & EHT_PER_STA_CTRL_TSF_OFFSET_PRESENT_MSK)) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: Per STA TSF offset not present");
+ goto out;
+ }
+
+ if (!(ctrl & EHT_PER_STA_CTRL_BEACON_INTERVAL_PRESENT_MSK)) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: Beacon interval not present");
+ goto out;
+ }
+
+ if (!(ctrl & EHT_PER_STA_CTRL_DTIM_INFO_PRESENT_MSK)) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: DTIM information not present");
+ goto out;
+ }
+
+ if (ctrl & EHT_PER_STA_CTRL_NSTR_LINK_PAIR_PRESENT_MSK) {
+ if (ctrl & EHT_PER_STA_CTRL_NSTR_BM_SIZE_MSK)
+ nstr_bitmap_len = 2;
+ else
+ nstr_bitmap_len = 1;
+ }
+
+ if (!(ctrl & EHT_PER_STA_CTRL_BSS_PARAM_CNT_PRESENT_MSK)) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: BSS params change count not present");
+ goto out;
+ }
+
+ sta_info_len = 1 + ETH_ALEN + 8 + 2 + 2 + 1 + nstr_bitmap_len;
+ if (sta_info_len > ml_len || sta_info_len > end - pos ||
+ sta_info_len + 2 > sub_elem_len ||
+ sta_info_len != *pos) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: Invalid STA info len=%u, len=%u",
+ sta_info_len, *pos);
+ goto out;
+ }
+
+ /* Get the link address */
+ wpa_printf(MSG_DEBUG,
+ "MLD: link addr: " MACSTR " nstr BM len=%u",
+ MAC2STR(pos + 1), nstr_bitmap_len);
+
+ ml_info[i].link_id = ctrl & EHT_PER_STA_CTRL_LINK_ID_MSK;
+ os_memcpy(ml_info[i].bssid, pos + 1, ETH_ALEN);
+
+ pos += sta_info_len;
+ ml_len -= sta_info_len;
+
+ wpa_printf(MSG_DEBUG, "MLD: sub_elem_len=%u, sta_info_len=%u",
+ sub_elem_len, sta_info_len);
+
+ sub_elem_len -= sta_info_len + 2;
+ if (sub_elem_len < 4) {
+ wpa_printf(MSG_DEBUG, "MLD: Per STA profile too short");
+ goto out;
+ }
+
+ wpa_hexdump(MSG_MSGDUMP, "MLD: STA profile", pos, sub_elem_len);
+ ml_info[i].status = WPA_GET_LE16(pos + 2);
+
+ pos += sub_elem_len;
+ ml_len -= sub_elem_len;
+
+ i++;
+ }
+
+ wpabuf_free(mlbuf);
+ return i;
+out:
+ wpabuf_free(mlbuf);
+ return 0;
+}
+
+
static int wpa_drv_get_mlo_info(struct wpa_supplicant *wpa_s)
{
struct driver_sta_mlo_info mlo;
@@ -3740,18 +4081,17 @@
if (!(mlo.valid_links & BIT(i)))
continue;
- if (os_memcmp(wpa_s->links[i].addr, mlo.links[i].addr,
- ETH_ALEN) != 0 ||
- os_memcmp(wpa_s->links[i].bssid, mlo.links[i].bssid,
- ETH_ALEN) != 0) {
+ if (!ether_addr_equal(wpa_s->links[i].addr,
+ mlo.links[i].addr) ||
+ !ether_addr_equal(wpa_s->links[i].bssid,
+ mlo.links[i].bssid)) {
match = false;
break;
}
}
if (match && wpa_s->mlo_assoc_link_id == mlo.assoc_link_id &&
- os_memcmp(wpa_s->ap_mld_addr, mlo.ap_mld_addr,
- ETH_ALEN) == 0)
+ ether_addr_equal(wpa_s->ap_mld_addr, mlo.ap_mld_addr))
return 0;
}
@@ -3939,7 +4279,7 @@
#endif
wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED);
- if (os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) {
+ if (!ether_addr_equal(bssid, wpa_s->bssid)) {
if (os_reltime_initialized(&wpa_s->session_start)) {
os_reltime_age(&wpa_s->session_start,
&wpa_s->session_length);
@@ -4138,9 +4478,9 @@
os_get_reltime(&now);
os_reltime_sub(&now, &wpa_s->pending_eapol_rx_time, &age);
if (age.sec == 0 && age.usec < 200000 &&
- os_memcmp(wpa_s->pending_eapol_rx_src,
- wpa_s->valid_links ? wpa_s->ap_mld_addr : bssid,
- ETH_ALEN) == 0) {
+ ether_addr_equal(wpa_s->pending_eapol_rx_src,
+ wpa_s->valid_links ? wpa_s->ap_mld_addr :
+ bssid)) {
wpa_dbg(wpa_s, MSG_DEBUG, "Process pending EAPOL "
"frame that was received just before "
"association notification");
@@ -4184,6 +4524,7 @@
wpas_wps_notify_assoc(wpa_s, bssid);
+#ifndef CONFIG_NO_WMM_AC
if (data) {
wmm_ac_notify_assoc(wpa_s, data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len,
@@ -4192,6 +4533,7 @@
if (wpa_s->reassoc_same_bss)
wmm_ac_restore_tspecs(wpa_s);
}
+#endif /* CONFIG_NO_WMM_AC */
#if defined(CONFIG_FILS) || defined(CONFIG_MBO)
bss = wpa_bss_get_bssid(wpa_s, bssid);
@@ -4284,16 +4626,10 @@
int locally_generated)
{
const u8 *bssid;
- int authenticating;
- u8 prev_pending_bssid[ETH_ALEN];
struct wpa_bss *fast_reconnect = NULL;
struct wpa_ssid *fast_reconnect_ssid = NULL;
- struct wpa_ssid *last_ssid;
struct wpa_bss *curr = NULL;
- authenticating = wpa_s->wpa_state == WPA_AUTHENTICATING;
- os_memcpy(prev_pending_bssid, wpa_s->pending_bssid, ETH_ALEN);
-
if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
/*
* At least Host AP driver and a Prism3 card seemed to be
@@ -4323,7 +4659,7 @@
"pre-shared key may be incorrect");
if (wpas_p2p_4way_hs_failed(wpa_s) > 0)
return; /* P2P group removed */
- wpas_auth_failed(wpa_s, "WRONG_KEY", prev_pending_bssid);
+ wpas_auth_failed(wpa_s, "WRONG_KEY", wpa_s->pending_bssid);
wpas_notify_psk_mismatch(wpa_s);
#ifdef CONFIG_DPP2
wpas_dpp_send_conn_status_result(wpa_s,
@@ -4374,7 +4710,7 @@
if (is_zero_ether_addr(bssid))
bssid = wpa_s->pending_bssid;
if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
- wpas_connection_failed(wpa_s, bssid);
+ wpas_connection_failed(wpa_s, bssid, NULL);
wpa_sm_notify_disassoc(wpa_s->wpa);
ptksa_cache_flush(wpa_s->ptksa, wpa_s->bssid, WPA_CIPHER_NONE);
@@ -4387,17 +4723,11 @@
wpa_dbg(wpa_s, MSG_DEBUG, "Disconnect event - remove keys");
wpa_clear_keys(wpa_s, wpa_s->bssid);
}
- last_ssid = wpa_s->current_ssid;
wpa_supplicant_mark_disassoc(wpa_s);
if (curr)
wpa_bss_remove(wpa_s, curr, "Connection to AP lost");
- if (authenticating && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)) {
- sme_disassoc_while_authenticating(wpa_s, prev_pending_bssid);
- wpa_s->current_ssid = last_ssid;
- }
-
if (fast_reconnect &&
!wpas_network_disabled(wpa_s, fast_reconnect_ssid) &&
!disallowed_bssid(wpa_s, fast_reconnect->bssid) &&
@@ -4747,7 +5077,7 @@
MACSTR " TargetAP " MACSTR " status %u",
MAC2STR(sta_addr), MAC2STR(target_ap_addr), status);
- if (os_memcmp(sta_addr, wpa_s->own_addr, ETH_ALEN) != 0) {
+ if (!ether_addr_equal(sta_addr, wpa_s->own_addr)) {
wpa_dbg(wpa_s, MSG_DEBUG, "FT: Foreign STA Address " MACSTR
" in FT Action Response", MAC2STR(sta_addr));
return;
@@ -4974,6 +5304,20 @@
}
+static void wpas_beacon_hint(struct wpa_supplicant *wpa_s, const char *title,
+ struct frequency_attrs *attrs)
+{
+ if (!attrs->freq)
+ return;
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REGDOM_BEACON_HINT
+ "%s freq=%u max_tx_power=%u%s%s%s",
+ title, attrs->freq, attrs->max_tx_power,
+ attrs->disabled ? " disabled=1" : "",
+ attrs->no_ir ? " no_ir=1" : "",
+ attrs->radar ? " radar=1" : "");
+}
+
+
void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s,
struct channel_list_changed *info)
{
@@ -4995,6 +5339,13 @@
reg_init_str(info->initiator), reg_type_str(info->type),
info->alpha2[0] ? " alpha2=" : "",
info->alpha2[0] ? info->alpha2 : "");
+
+ if (info->initiator == REGDOM_BEACON_HINT) {
+ wpas_beacon_hint(ifs, "before",
+ &info->beacon_hint_before);
+ wpas_beacon_hint(ifs, "after",
+ &info->beacon_hint_after);
+ }
}
if (wpa_s->drv_priv == NULL)
@@ -5055,10 +5406,12 @@
" Category=%u DataLen=%d freq=%d MHz",
MAC2STR(mgmt->sa), category, (int) plen, freq);
+#ifndef CONFIG_NO_WMM_AC
if (category == WLAN_ACTION_WMM) {
wmm_ac_rx_action(wpa_s, mgmt->da, mgmt->sa, payload, plen);
return;
}
+#endif /* CONFIG_NO_WMM_AC */
#ifdef CONFIG_IEEE80211R
if (category == WLAN_ACTION_FT) {
@@ -5122,7 +5475,7 @@
size_t qlen = plen - 1;
wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: Received QoS Map Configure frame from "
MACSTR, MAC2STR(mgmt->sa));
- if (os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) == 0 &&
+ if (ether_addr_equal(mgmt->sa, wpa_s->bssid) &&
qlen > 2 && pos[0] == WLAN_EID_QOS_MAP_SET &&
pos[1] <= qlen - 2 && pos[1] >= 16)
wpas_qos_map_set(wpa_s, pos + 2, pos[1]);
@@ -5130,6 +5483,7 @@
}
#endif /* CONFIG_INTERWORKING */
+#ifndef CONFIG_NO_RRM
if (category == WLAN_ACTION_RADIO_MEASUREMENT &&
payload[0] == WLAN_RRM_RADIO_MEASUREMENT_REQUEST) {
wpas_rrm_handle_radio_measurement_request(wpa_s, mgmt->sa,
@@ -5152,6 +5506,7 @@
rssi);
return;
}
+#endif /* CONFIG_NO_RRM */
#ifdef CONFIG_FST
if (mgmt->u.action.category == WLAN_ACTION_FST && wpa_s->fst) {
@@ -5160,6 +5515,17 @@
}
#endif /* CONFIG_FST */
+#ifdef CONFIG_NAN_USD
+ if (category == WLAN_ACTION_PUBLIC && plen >= 5 &&
+ payload[0] == WLAN_PA_VENDOR_SPECIFIC &&
+ WPA_GET_BE32(&payload[1]) == NAN_SDF_VENDOR_TYPE) {
+ payload += 5;
+ plen -= 5;
+ wpas_nan_usd_rx_sdf(wpa_s, mgmt->sa, freq, payload, plen);
+ return;
+ }
+#endif /* CONFIG_NAN_USD */
+
#ifdef CONFIG_DPP
if (category == WLAN_ACTION_PUBLIC && plen >= 5 &&
payload[0] == WLAN_PA_VENDOR_SPECIFIC &&
@@ -5172,6 +5538,7 @@
}
#endif /* CONFIG_DPP */
+#ifndef CONFIG_NO_ROBUST_AV
if (category == WLAN_ACTION_ROBUST_AV_STREAMING &&
payload[0] == ROBUST_AV_SCS_RESP) {
wpas_handle_robust_av_scs_recv_action(wpa_s, mgmt->sa,
@@ -5192,6 +5559,7 @@
payload + 4, plen - 4);
return;
}
+#endif /* CONFIG_NO_ROBUST_AV */
wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
category, payload, plen, freq);
@@ -5395,6 +5763,8 @@
union wpa_event_data *data)
{
const u8 *bssid = data->assoc_reject.bssid;
+ struct ieee802_11_elems elems;
+ const u8 *link_bssids[MAX_NUM_MLD_LINKS];
#ifdef CONFIG_MBO
struct wpa_bss *reject_bss;
#endif /* CONFIG_MBO */
@@ -5450,7 +5820,7 @@
if (!bss) {
bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
if (!bss) {
- wpas_connection_failed(wpa_s, bssid);
+ wpas_connection_failed(wpa_s, bssid, NULL);
wpa_supplicant_mark_disassoc(wpa_s);
return;
}
@@ -5485,7 +5855,7 @@
if (!bss || wpa_s->dpp_pfs_fallback) {
wpa_printf(MSG_DEBUG,
"DPP: Updated PFS policy for next try");
- wpas_connection_failed(wpa_s, bssid);
+ wpas_connection_failed(wpa_s, bssid, NULL);
wpa_supplicant_mark_disassoc(wpa_s);
return;
}
@@ -5522,8 +5892,34 @@
}
#endif /* CONFIG_MBO */
+ /* Check for other failed links in the response */
+ os_memset(link_bssids, 0, sizeof(link_bssids));
+ if (ieee802_11_parse_elems(data->assoc_reject.resp_ies,
+ data->assoc_reject.resp_ies_len,
+ &elems, 1) != ParseFailed) {
+ struct ml_sta_link_info ml_info[MAX_NUM_MLD_LINKS];
+ unsigned int n_links, i, idx;
+
+ idx = 0;
+ n_links = wpas_ml_parse_assoc(wpa_s, &elems, ml_info);
+
+ for (i = 1; i < n_links; i++) {
+ /* The status cannot be success here.
+ * Add the link to the failed list if it is reporting
+ * an error. The only valid "non-error" status is
+ * TX_LINK_NOT_ACCEPTED as that means this link may
+ * still accept an association from us.
+ */
+ if (ml_info[i].status !=
+ WLAN_STATUS_DENIED_TX_LINK_NOT_ACCEPTED) {
+ link_bssids[idx] = ml_info[i].bssid;
+ idx++;
+ }
+ }
+ }
+
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) {
- sme_event_assoc_reject(wpa_s, data);
+ sme_event_assoc_reject(wpa_s, data, link_bssids);
return;
}
@@ -5560,7 +5956,7 @@
}
#endif /* CONFIG_FILS */
- wpas_connection_failed(wpa_s, bssid);
+ wpas_connection_failed(wpa_s, bssid, link_bssids);
wpa_supplicant_mark_disassoc(wpa_s);
}
@@ -5572,7 +5968,7 @@
int res;
if (!data || wpa_s->wpa_state != WPA_COMPLETED ||
- os_memcmp(data->sa, wpa_s->bssid, ETH_ALEN) != 0)
+ !ether_addr_equal(data->sa, wpa_s->bssid))
return;
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_UNPROT_BEACON MACSTR,
MAC2STR(data->sa));
@@ -5662,7 +6058,7 @@
return;
}
- if (os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) {
+ if (!ether_addr_equal(bssid, wpa_s->bssid)) {
os_memcpy(wpa_s->bssid, bssid, ETH_ALEN);
wpa_supplicant_update_current_bss(wpa_s, wpa_s->bssid);
wpas_notify_bssid_changed(wpa_s);
@@ -5947,8 +6343,8 @@
*/
if (data->tx_status.type == WLAN_FC_TYPE_MGMT &&
data->tx_status.stype == WLAN_FC_STYPE_ACTION &&
- os_memcmp(wpa_s->p2pdev->pending_action_dst,
- data->tx_status.dst, ETH_ALEN) == 0) {
+ ether_addr_equal(wpa_s->p2pdev->pending_action_dst,
+ data->tx_status.dst)) {
offchannel_send_action_tx_status(
wpa_s->p2pdev, data->tx_status.dst,
data->tx_status.data,
@@ -6271,6 +6667,11 @@
wpa_s, data->remain_on_channel.freq,
data->remain_on_channel.duration);
#endif /* CONFIG_DPP */
+#ifdef CONFIG_NAN_USD
+ wpas_nan_usd_remain_on_channel_cb(
+ wpa_s, data->remain_on_channel.freq,
+ data->remain_on_channel.duration);
+#endif /* CONFIG_NAN_USD */
break;
case EVENT_CANCEL_REMAIN_ON_CHANNEL:
#ifdef CONFIG_OFFCHANNEL
@@ -6283,6 +6684,10 @@
wpas_dpp_cancel_remain_on_channel_cb(
wpa_s, data->remain_on_channel.freq);
#endif /* CONFIG_DPP */
+#ifdef CONFIG_NAN_USD
+ wpas_nan_usd_cancel_remain_on_channel_cb(
+ wpa_s, data->remain_on_channel.freq);
+#endif /* CONFIG_NAN_USD */
break;
case EVENT_EAPOL_RX:
wpa_supplicant_rx_eapol(wpa_s, data->eapol_rx.src,
@@ -6321,7 +6726,7 @@
wpa_s, NULL);
os_memcpy(addr, wpa_s->own_addr, ETH_ALEN);
wpa_supplicant_update_mac_addr(wpa_s);
- if (os_memcmp(addr, wpa_s->own_addr, ETH_ALEN) != 0)
+ if (!ether_addr_equal(addr, wpa_s->own_addr))
wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
else
wpa_sm_pmksa_cache_reconfig(wpa_s->wpa);
@@ -6455,8 +6860,8 @@
#endif /* CONFIG_IBSS_RSN */
break;
case EVENT_DRIVER_GTK_REKEY:
- if (os_memcmp(data->driver_gtk_rekey.bssid,
- wpa_s->bssid, ETH_ALEN))
+ if (!ether_addr_equal(data->driver_gtk_rekey.bssid,
+ wpa_s->bssid))
break;
if (!wpa_s->wpa)
break;
@@ -6618,6 +7023,9 @@
#ifdef CONFIG_DPP
wpas_dpp_tx_wait_expire(wpa_s);
#endif /* CONFIG_DPP */
+#ifdef CONFIG_NAN_USD
+ wpas_nan_usd_tx_wait_expire(wpa_s);
+#endif /* CONFIG_NAN_USD */
break;
case EVENT_TID_LINK_MAP:
if (data)
diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c
index c301f74..7d29931 100644
--- a/wpa_supplicant/gas_query.c
+++ b/wpa_supplicant/gas_query.c
@@ -199,10 +199,16 @@
gas_query_get_pending(struct gas_query *gas, const u8 *addr, u8 dialog_token)
{
struct gas_query_pending *q;
+ struct wpa_supplicant *wpa_s = gas->wpa_s;
+
dl_list_for_each(q, &gas->pending, struct gas_query_pending, list) {
- if (os_memcmp(q->addr, addr, ETH_ALEN) == 0 &&
+ if (ether_addr_equal(q->addr, addr) &&
q->dialog_token == dialog_token)
return q;
+ if (wpa_s->valid_links &&
+ ether_addr_equal(wpa_s->ap_mld_addr, addr) &&
+ wpas_ap_link_address(wpa_s, q->addr))
+ return q;
}
return NULL;
}
@@ -243,7 +249,7 @@
wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
" result=%d query=%p dialog_token=%u dur=%d ms",
freq, MAC2STR(dst), result, query, query->dialog_token, dur);
- if (os_memcmp(dst, query->addr, ETH_ALEN) != 0) {
+ if (!ether_addr_equal(dst, query->addr)) {
wpa_printf(MSG_DEBUG, "GAS: TX status for unexpected destination");
return;
}
@@ -300,7 +306,7 @@
(!gas->wpa_s->conf->gas_address3 ||
(gas->wpa_s->current_ssid &&
gas->wpa_s->wpa_state >= WPA_ASSOCIATED &&
- os_memcmp(query->addr, gas->wpa_s->bssid, ETH_ALEN) == 0)))
+ ether_addr_equal(query->addr, gas->wpa_s->bssid))))
bssid = query->addr;
else
bssid = wildcard_bssid;
@@ -668,7 +674,7 @@
{
struct gas_query_pending *q;
dl_list_for_each(q, &gas->pending, struct gas_query_pending, list) {
- if (os_memcmp(dst, q->addr, ETH_ALEN) == 0 &&
+ if (ether_addr_equal(dst, q->addr) &&
dialog_token == q->dialog_token)
return 0;
}
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index eaf0803..c68167f 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -27,6 +27,7 @@
#include "interworking.h"
#include "hs20_supplicant.h"
#include "base64.h"
+#include "notify.h"
#define OSU_MAX_ITEMS 10
@@ -68,7 +69,6 @@
void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s)
{
struct wpa_bss *bss = wpa_s->current_bss;
- u8 *bssid = wpa_s->bssid;
const u8 *ie;
const u8 *ext_capa;
u32 filter = 0;
@@ -79,9 +79,8 @@
|| !is_hs20_config(wpa_s)
#endif
) {
- wpa_printf(MSG_DEBUG,
- "Not configuring frame filtering - BSS " MACSTR
- " is not a Hotspot 2.0 network", MAC2STR(bssid));
+ /* Not configuring frame filtering - BSS is not a Hotspot 2.0
+ * network */
return;
}
@@ -336,7 +335,7 @@
struct icon_entry *icon;
dl_list_for_each(icon, &wpa_s->icon_head, struct icon_entry, list) {
- if (os_memcmp(icon->bssid, bssid, ETH_ALEN) == 0 &&
+ if (ether_addr_equal(icon->bssid, bssid) &&
os_strcmp(icon->file_name, file_name) == 0 && icon->image)
return icon;
}
@@ -412,7 +411,7 @@
dl_list_for_each_safe(icon, tmp, &wpa_s->icon_head, struct icon_entry,
list) {
- if ((!bssid || os_memcmp(icon->bssid, bssid, ETH_ALEN) == 0) &&
+ if ((!bssid || ether_addr_equal(icon->bssid, bssid)) &&
(!file_name ||
os_strcmp(icon->file_name, file_name) == 0)) {
dl_list_del(&icon->list);
@@ -458,7 +457,7 @@
list) {
if (icon == new_icon)
continue;
- if (os_memcmp(icon->bssid, new_icon->bssid, ETH_ALEN) == 0 &&
+ if (ether_addr_equal(icon->bssid, new_icon->bssid) &&
os_strcmp(icon->file_name, new_icon->file_name) == 0) {
dl_list_del(&icon->list);
hs20_free_icon_entry(icon);
@@ -479,7 +478,7 @@
dl_list_for_each(icon, &wpa_s->icon_head, struct icon_entry, list) {
if (icon->dialog_token == dialog_token && !icon->image &&
- os_memcmp(icon->bssid, sa, ETH_ALEN) == 0) {
+ ether_addr_equal(icon->bssid, sa)) {
icon->image = os_memdup(pos, slen);
if (!icon->image)
return -1;
@@ -1354,8 +1353,7 @@
return;
}
- wpa_msg(wpa_s, MSG_INFO, HS20_T_C_ACCEPTANCE "%s", url);
- wpas_notify_hs20_rx_terms_and_conditions_acceptance(wpa_s, url);
+ wpas_notify_hs20_t_c_acceptance(wpa_s, url);
}
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index 5b31f7b..554268a 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -30,7 +30,7 @@
struct ibss_rsn_peer *peer;
for (peer = ibss_rsn->peers; peer; peer = peer->next)
- if (os_memcmp(addr, peer->addr, ETH_ALEN) == 0)
+ if (ether_addr_equal(addr, peer->addr))
break;
return peer;
}
@@ -672,7 +672,7 @@
for (prev = NULL, peer = ibss_rsn->peers; peer != NULL;
prev = peer, peer = peer->next) {
- if (os_memcmp(peermac, peer->addr, ETH_ALEN) == 0) {
+ if (ether_addr_equal(peermac, peer->addr)) {
if (prev == NULL)
ibss_rsn->peers = peer->next;
else
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index cb1165e..498cc98 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -2674,7 +2674,7 @@
continue;
if (!(other->flags & WPA_BSS_ANQP_FETCH_TRIED))
continue;
- if (os_memcmp(bss->hessid, other->hessid, ETH_ALEN) != 0)
+ if (!ether_addr_equal(bss->hessid, other->hessid))
continue;
if (bss->ssid_len != other->ssid_len ||
os_memcmp(bss->ssid, other->ssid, bss->ssid_len) != 0)
@@ -3169,7 +3169,7 @@
*/
dl_list_for_each_reverse(tmp, &wpa_s->bss, struct wpa_bss, list) {
if (tmp == wpa_s->interworking_gas_bss &&
- os_memcmp(tmp->bssid, dst, ETH_ALEN) == 0) {
+ ether_addr_equal(tmp->bssid, dst)) {
bss = tmp;
break;
}
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index 138c013..b2fc127 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -468,6 +468,7 @@
params.plink_state = state;
params.peer_aid = sta->peer_aid;
params.set = 1;
+ params.mld_link_id = -1;
ret = wpa_drv_sta_add(wpa_s, ¶ms);
if (ret) {
@@ -697,6 +698,7 @@
params.addr = sta->addr;
params.flags = WPA_STA_AUTHENTICATED | WPA_STA_AUTHORIZED;
params.set = 1;
+ params.mld_link_id = -1;
wpa_msg(wpa_s, MSG_DEBUG, "MPM authenticating " MACSTR,
MAC2STR(sta->addr));
@@ -816,6 +818,7 @@
params.eht_capab_len = sta->eht_capab_len;
params.flags |= WPA_STA_WMM;
params.flags_mask |= WPA_STA_AUTHENTICATED;
+ params.mld_link_id = -1;
if (conf->security == MESH_CONF_SEC_NONE) {
params.flags |= WPA_STA_AUTHORIZED;
params.flags |= WPA_STA_AUTHENTICATED;
@@ -851,7 +854,7 @@
if (ssid && ssid->no_auto_peer &&
(is_zero_ether_addr(data->mesh_required_peer) ||
- os_memcmp(data->mesh_required_peer, addr, ETH_ALEN) != 0)) {
+ !ether_addr_equal(data->mesh_required_peer, addr))) {
wpa_msg(wpa_s, MSG_INFO, "will not initiate new peer link with "
MACSTR " because of no_auto_peer", MAC2STR(addr));
if (data->mesh_pending_auth) {
@@ -862,7 +865,7 @@
mgmt = wpabuf_head(data->mesh_pending_auth);
os_reltime_age(&data->mesh_pending_auth_time, &age);
if (age.sec < 2 &&
- os_memcmp(mgmt->sa, addr, ETH_ALEN) == 0) {
+ ether_addr_equal(mgmt->sa, addr)) {
wpa_printf(MSG_DEBUG,
"mesh: Process pending Authentication frame from %u.%06u seconds ago",
(unsigned int) age.sec,
diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c
index 12dcc30..ada53c7 100644
--- a/wpa_supplicant/mesh_rsn.c
+++ b/wpa_supplicant/mesh_rsn.c
@@ -142,6 +142,23 @@
}
+static int auth_for_each_sta(
+ void *ctx, int (*cb)(struct wpa_state_machine *sm, void *ctx),
+ void *cb_ctx)
+{
+ struct mesh_rsn *rsn = ctx;
+ struct hostapd_data *hapd;
+ struct sta_info *sta;
+
+ hapd = rsn->wpa_s->ifmsh->bss[0];
+ for (sta = hapd->sta_list; sta; sta = sta->next) {
+ if (sta->wpa_sm && cb(sta->wpa_sm, cb_ctx))
+ return 1;
+ }
+ return 0;
+}
+
+
static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr,
enum mfp_options ieee80211w, int ocv)
{
@@ -151,6 +168,7 @@
.get_psk = auth_get_psk,
.set_key = auth_set_key,
.start_ampe = auth_start_ampe,
+ .for_each_sta = auth_for_each_sta,
};
u8 seq[6] = {};
@@ -386,7 +404,8 @@
" - try to use PMKSA caching instead of new SAE authentication",
MAC2STR(sta->addr));
wpa_auth_pmksa_set_to_sm(pmksa, sta->wpa_sm, hapd->wpa_auth,
- sta->sae->pmkid, sta->sae->pmk);
+ sta->sae->pmkid, sta->sae->pmk,
+ &sta->sae->pmk_len);
sae_accept_sta(hapd, sta);
sta->mesh_sae_pmksa_caching = 1;
return 0;
diff --git a/wpa_supplicant/nan_usd.c b/wpa_supplicant/nan_usd.c
new file mode 100644
index 0000000..657b302
--- /dev/null
+++ b/wpa_supplicant/nan_usd.c
@@ -0,0 +1,513 @@
+/*
+ * NAN unsynchronized service discovery (USD)
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "common/nan_de.h"
+#include "wpa_supplicant_i.h"
+#include "offchannel.h"
+#include "driver_i.h"
+#include "nan_usd.h"
+
+
+static const char *
+tx_status_result_txt(enum offchannel_send_action_result result)
+{
+ switch (result) {
+ case OFFCHANNEL_SEND_ACTION_SUCCESS:
+ return "success";
+ case OFFCHANNEL_SEND_ACTION_NO_ACK:
+ return "no-ack";
+ case OFFCHANNEL_SEND_ACTION_FAILED:
+ return "failed";
+ }
+
+ return "?";
+}
+
+
+static void wpas_nan_de_tx_status(struct wpa_supplicant *wpa_s,
+ unsigned int freq, const u8 *dst,
+ const u8 *src, const u8 *bssid,
+ const u8 *data, size_t data_len,
+ enum offchannel_send_action_result result)
+{
+ if (!wpa_s->nan_de)
+ return;
+
+ wpa_printf(MSG_DEBUG, "NAN: TX status A1=" MACSTR " A2=" MACSTR
+ " A3=" MACSTR " freq=%d len=%zu result=%s",
+ MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), freq,
+ data_len, tx_status_result_txt(result));
+
+ nan_de_tx_status(wpa_s->nan_de, freq, dst);
+}
+
+
+struct wpas_nan_usd_tx_work {
+ unsigned int freq;
+ unsigned int wait_time;
+ u8 dst[ETH_ALEN];
+ u8 src[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
+ struct wpabuf *buf;
+};
+
+
+static void wpas_nan_usd_tx_work_free(struct wpas_nan_usd_tx_work *twork)
+{
+ if (!twork)
+ return;
+ wpabuf_free(twork->buf);
+ os_free(twork);
+}
+
+
+static void wpas_nan_usd_tx_work_done(struct wpa_supplicant *wpa_s)
+{
+ struct wpas_nan_usd_tx_work *twork;
+
+ if (!wpa_s->nan_usd_tx_work)
+ return;
+
+ twork = wpa_s->nan_usd_tx_work->ctx;
+ wpas_nan_usd_tx_work_free(twork);
+ radio_work_done(wpa_s->nan_usd_tx_work);
+ wpa_s->nan_usd_tx_work = NULL;
+}
+
+
+static int wpas_nan_de_tx_send(struct wpa_supplicant *wpa_s, unsigned int freq,
+ unsigned int wait_time, const u8 *dst,
+ const u8 *src, const u8 *bssid,
+ const struct wpabuf *buf)
+{
+ wpa_printf(MSG_DEBUG, "NAN: TX NAN SDF A1=" MACSTR " A2=" MACSTR
+ " A3=" MACSTR " freq=%d len=%zu",
+ MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), freq,
+ wpabuf_len(buf));
+
+ return offchannel_send_action(wpa_s, freq, dst, src, bssid,
+ wpabuf_head(buf), wpabuf_len(buf),
+ wait_time, wpas_nan_de_tx_status, 1);
+}
+
+
+static void wpas_nan_usd_start_tx_cb(struct wpa_radio_work *work, int deinit)
+{
+ struct wpa_supplicant *wpa_s = work->wpa_s;
+ struct wpas_nan_usd_tx_work *twork = work->ctx;
+
+ if (deinit) {
+ if (work->started) {
+ wpa_s->nan_usd_tx_work = NULL;
+ offchannel_send_action_done(wpa_s);
+ }
+ wpas_nan_usd_tx_work_free(twork);
+ return;
+ }
+
+ wpa_s->nan_usd_tx_work = work;
+
+ if (wpas_nan_de_tx_send(wpa_s, twork->freq, twork->wait_time,
+ twork->dst, twork->src, twork->bssid,
+ twork->buf) < 0)
+ wpas_nan_usd_tx_work_done(wpa_s);
+}
+
+
+static int wpas_nan_de_tx(void *ctx, unsigned int freq, unsigned int wait_time,
+ const u8 *dst, const u8 *src, const u8 *bssid,
+ const struct wpabuf *buf)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ struct wpas_nan_usd_tx_work *twork;
+
+ if (wpa_s->nan_usd_tx_work || wpa_s->nan_usd_listen_work) {
+ /* Reuse ongoing radio work */
+ return wpas_nan_de_tx_send(wpa_s, freq, wait_time, dst, src,
+ bssid, buf);
+ }
+
+ twork = os_zalloc(sizeof(*twork));
+ if (!twork)
+ return -1;
+ twork->freq = freq;
+ twork->wait_time = wait_time;
+ os_memcpy(twork->dst, dst, ETH_ALEN);
+ os_memcpy(twork->src, src, ETH_ALEN);
+ os_memcpy(twork->bssid, bssid, ETH_ALEN);
+ twork->buf = wpabuf_dup(buf);
+ if (!twork->buf) {
+ wpas_nan_usd_tx_work_free(twork);
+ return -1;
+ }
+
+ if (radio_add_work(wpa_s, freq, "nan-usd-tx", 0,
+ wpas_nan_usd_start_tx_cb, twork) < 0) {
+ wpas_nan_usd_tx_work_free(twork);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+struct wpas_nan_usd_listen_work {
+ unsigned int freq;
+ unsigned int duration;
+};
+
+
+static void wpas_nan_usd_listen_work_done(struct wpa_supplicant *wpa_s)
+{
+ struct wpas_nan_usd_listen_work *lwork;
+
+ if (!wpa_s->nan_usd_listen_work)
+ return;
+
+ lwork = wpa_s->nan_usd_listen_work->ctx;
+ os_free(lwork);
+ radio_work_done(wpa_s->nan_usd_listen_work);
+ wpa_s->nan_usd_listen_work = NULL;
+}
+
+
+static void wpas_nan_usd_start_listen_cb(struct wpa_radio_work *work,
+ int deinit)
+{
+ struct wpa_supplicant *wpa_s = work->wpa_s;
+ struct wpas_nan_usd_listen_work *lwork = work->ctx;
+ unsigned int duration;
+
+ if (deinit) {
+ if (work->started) {
+ wpa_s->nan_usd_listen_work = NULL;
+ wpa_drv_cancel_remain_on_channel(wpa_s);
+ }
+ os_free(lwork);
+ return;
+ }
+
+ wpa_s->nan_usd_listen_work = work;
+
+ duration = lwork->duration;
+ if (duration > wpa_s->max_remain_on_chan)
+ duration = wpa_s->max_remain_on_chan;
+ wpa_printf(MSG_DEBUG, "NAN: Start listen on %u MHz for %u ms",
+ lwork->freq, duration);
+ if (wpa_drv_remain_on_channel(wpa_s, lwork->freq, duration) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Failed to request the driver to remain on channel (%u MHz) for listen",
+ lwork->freq);
+ wpas_nan_usd_listen_work_done(wpa_s);
+ return;
+ }
+}
+
+
+static int wpas_nan_de_listen(void *ctx, unsigned int freq,
+ unsigned int duration)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ struct wpas_nan_usd_listen_work *lwork;
+
+ lwork = os_zalloc(sizeof(*lwork));
+ if (!lwork)
+ return -1;
+ lwork->freq = freq;
+ lwork->duration = duration;
+
+ if (radio_add_work(wpa_s, freq, "nan-usd-listen", 0,
+ wpas_nan_usd_start_listen_cb, lwork) < 0) {
+ os_free(lwork);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static void
+wpas_nan_de_discovery_result(void *ctx, int subscribe_id,
+ enum nan_service_protocol_type srv_proto_type,
+ const u8 *ssi, size_t ssi_len, int peer_publish_id,
+ const u8 *peer_addr, bool fsd, bool fsd_gas)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ char *ssi_hex;
+
+ ssi_hex = os_zalloc(2 * ssi_len + 1);
+ if (!ssi_hex)
+ return;
+ if (ssi)
+ wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
+ wpa_msg(wpa_s, MSG_INFO, NAN_DISCOVERY_RESULT
+ "subscribe_id=%d publish_id=%d address=" MACSTR
+ " fsd=%d fsd_gas=%d srv_proto_type=%u ssi=%s",
+ subscribe_id, peer_publish_id, MAC2STR(peer_addr),
+ fsd, fsd_gas, srv_proto_type, ssi_hex);
+ os_free(ssi_hex);
+}
+
+
+static void wpas_nan_de_replied(void *ctx, int publish_id, const u8 *peer_addr,
+ int peer_subscribe_id,
+ enum nan_service_protocol_type srv_proto_type,
+ const u8 *ssi, size_t ssi_len)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ char *ssi_hex;
+
+ ssi_hex = os_zalloc(2 * ssi_len + 1);
+ if (!ssi_hex)
+ return;
+ if (ssi)
+ wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
+ wpa_msg(wpa_s, MSG_INFO, NAN_REPLIED
+ "publish_id=%d address=" MACSTR
+ " subscribe_id=%d srv_proto_type=%u ssi=%s",
+ publish_id, MAC2STR(peer_addr), peer_subscribe_id,
+ srv_proto_type, ssi_hex);
+ os_free(ssi_hex);
+}
+
+
+static const char * nan_reason_txt(enum nan_de_reason reason)
+{
+ switch (reason) {
+ case NAN_DE_REASON_TIMEOUT:
+ return "timeout";
+ case NAN_DE_REASON_USER_REQUEST:
+ return "user-request";
+ case NAN_DE_REASON_FAILURE:
+ return "failure";
+ }
+
+ return "unknown";
+}
+
+
+static void wpas_nan_de_publish_terminated(void *ctx, int publish_id,
+ enum nan_de_reason reason)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+
+ wpa_msg(wpa_s, MSG_INFO, NAN_PUBLISH_TERMINATED
+ "publish_id=%d reason=%s",
+ publish_id, nan_reason_txt(reason));
+}
+
+
+static void wpas_nan_de_subscribe_terminated(void *ctx, int subscribe_id,
+ enum nan_de_reason reason)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+
+ wpa_msg(wpa_s, MSG_INFO, NAN_SUBSCRIBE_TERMINATED
+ "subscribe_id=%d reason=%s",
+ subscribe_id, nan_reason_txt(reason));
+}
+
+
+static void wpas_nan_de_receive(void *ctx, int id, int peer_instance_id,
+ const u8 *ssi, size_t ssi_len,
+ const u8 *peer_addr)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ char *ssi_hex;
+
+ ssi_hex = os_zalloc(2 * ssi_len + 1);
+ if (!ssi_hex)
+ return;
+ if (ssi)
+ wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
+ wpa_msg(wpa_s, MSG_INFO, NAN_RECEIVE
+ "id=%d peer_instance_id=%d address=" MACSTR " ssi=%s",
+ id, peer_instance_id, MAC2STR(peer_addr), ssi_hex);
+ os_free(ssi_hex);
+}
+
+
+int wpas_nan_usd_init(struct wpa_supplicant *wpa_s)
+{
+ struct nan_callbacks cb;
+
+ os_memset(&cb, 0, sizeof(cb));
+ cb.ctx = wpa_s;
+ cb.tx = wpas_nan_de_tx;
+ cb.listen = wpas_nan_de_listen;
+ cb.discovery_result = wpas_nan_de_discovery_result;
+ cb.replied = wpas_nan_de_replied;
+ cb.publish_terminated = wpas_nan_de_publish_terminated;
+ cb.subscribe_terminated = wpas_nan_de_subscribe_terminated;
+ cb.receive = wpas_nan_de_receive;
+
+ wpa_s->nan_de = nan_de_init(wpa_s->own_addr, false, &cb);
+ if (!wpa_s->nan_de)
+ return -1;
+ return 0;
+}
+
+
+void wpas_nan_usd_deinit(struct wpa_supplicant *wpa_s)
+{
+ nan_de_deinit(wpa_s->nan_de);
+ wpa_s->nan_de = NULL;
+}
+
+
+void wpas_nan_usd_rx_sdf(struct wpa_supplicant *wpa_s, const u8 *src,
+ unsigned int freq, const u8 *buf, size_t len)
+{
+ if (!wpa_s->nan_de)
+ return;
+ nan_de_rx_sdf(wpa_s->nan_de, src, freq, buf, len);
+}
+
+
+void wpas_nan_usd_flush(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s->nan_de)
+ return;
+ nan_de_flush(wpa_s->nan_de);
+}
+
+
+int wpas_nan_usd_publish(struct wpa_supplicant *wpa_s, const char *service_name,
+ enum nan_service_protocol_type srv_proto_type,
+ const struct wpabuf *ssi,
+ struct nan_publish_params *params)
+{
+ int publish_id;
+ struct wpabuf *elems = NULL;
+
+ if (!wpa_s->nan_de)
+ return -1;
+
+ publish_id = nan_de_publish(wpa_s->nan_de, service_name, srv_proto_type,
+ ssi, elems, params);
+ wpabuf_free(elems);
+ return publish_id;
+}
+
+
+void wpas_nan_usd_cancel_publish(struct wpa_supplicant *wpa_s, int publish_id)
+{
+ if (!wpa_s->nan_de)
+ return;
+ nan_de_cancel_publish(wpa_s->nan_de, publish_id);
+}
+
+
+int wpas_nan_usd_update_publish(struct wpa_supplicant *wpa_s, int publish_id,
+ const struct wpabuf *ssi)
+{
+ if (!wpa_s->nan_de)
+ return -1;
+ return nan_de_update_publish(wpa_s->nan_de, publish_id, ssi);
+}
+
+
+int wpas_nan_usd_subscribe(struct wpa_supplicant *wpa_s,
+ const char *service_name,
+ enum nan_service_protocol_type srv_proto_type,
+ const struct wpabuf *ssi,
+ struct nan_subscribe_params *params)
+{
+ int subscribe_id;
+ struct wpabuf *elems = NULL;
+
+ if (!wpa_s->nan_de)
+ return -1;
+
+ subscribe_id = nan_de_subscribe(wpa_s->nan_de, service_name,
+ srv_proto_type, ssi, elems, params);
+ wpabuf_free(elems);
+ return subscribe_id;
+}
+
+
+void wpas_nan_usd_cancel_subscribe(struct wpa_supplicant *wpa_s,
+ int subscribe_id)
+{
+ if (!wpa_s->nan_de)
+ return;
+ nan_de_cancel_subscribe(wpa_s->nan_de, subscribe_id);
+}
+
+
+int wpas_nan_usd_transmit(struct wpa_supplicant *wpa_s, int handle,
+ const struct wpabuf *ssi, const struct wpabuf *elems,
+ const u8 *peer_addr, u8 req_instance_id)
+{
+ if (!wpa_s->nan_de)
+ return -1;
+ return nan_de_transmit(wpa_s->nan_de, handle, ssi, elems, peer_addr,
+ req_instance_id);
+}
+
+
+void wpas_nan_usd_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
+ unsigned int freq, unsigned int duration)
+{
+ wpas_nan_usd_listen_work_done(wpa_s);
+
+ if (wpa_s->nan_de)
+ nan_de_listen_started(wpa_s->nan_de, freq, duration);
+}
+
+
+void wpas_nan_usd_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
+ unsigned int freq)
+{
+ if (wpa_s->nan_de)
+ nan_de_listen_ended(wpa_s->nan_de, freq);
+}
+
+
+void wpas_nan_usd_tx_wait_expire(struct wpa_supplicant *wpa_s)
+{
+ wpas_nan_usd_tx_work_done(wpa_s);
+
+ if (wpa_s->nan_de)
+ nan_de_tx_wait_ended(wpa_s->nan_de);
+}
+
+
+int * wpas_nan_usd_all_freqs(struct wpa_supplicant *wpa_s)
+{
+ int i, j;
+ int *freqs = NULL;
+
+ if (!wpa_s->hw.modes)
+ return NULL;
+
+ for (i = 0; i < wpa_s->hw.num_modes; i++) {
+ struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
+
+ for (j = 0; j < mode->num_channels; j++) {
+ struct hostapd_channel_data *chan = &mode->channels[j];
+
+ /* All 20 MHz channels on 2.4 and 5 GHz band */
+ if (chan->freq < 2412 || chan->freq > 5900)
+ continue;
+
+ /* that allow frames to be transmitted */
+ if (chan->flag & (HOSTAPD_CHAN_DISABLED |
+ HOSTAPD_CHAN_NO_IR |
+ HOSTAPD_CHAN_RADAR))
+ continue;
+
+ int_array_add_unique(&freqs, chan->freq);
+ }
+ }
+
+ return freqs;
+}
diff --git a/wpa_supplicant/nan_usd.h b/wpa_supplicant/nan_usd.h
new file mode 100644
index 0000000..149ac9e
--- /dev/null
+++ b/wpa_supplicant/nan_usd.h
@@ -0,0 +1,46 @@
+/*
+ * NAN unsynchronized service discovery (USD)
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef NAN_USD_H
+#define NAN_USD_H
+
+struct nan_subscribe_params;
+struct nan_publish_params;
+enum nan_service_protocol_type;
+
+int wpas_nan_usd_init(struct wpa_supplicant *wpa_s);
+void wpas_nan_usd_deinit(struct wpa_supplicant *wpa_s);
+void wpas_nan_usd_rx_sdf(struct wpa_supplicant *wpa_s, const u8 *src,
+ unsigned int freq, const u8 *buf, size_t len);
+void wpas_nan_usd_flush(struct wpa_supplicant *wpa_s);
+int wpas_nan_usd_publish(struct wpa_supplicant *wpa_s, const char *service_name,
+ enum nan_service_protocol_type srv_proto_type,
+ const struct wpabuf *ssi,
+ struct nan_publish_params *params);
+void wpas_nan_usd_cancel_publish(struct wpa_supplicant *wpa_s, int publish_id);
+int wpas_nan_usd_update_publish(struct wpa_supplicant *wpa_s, int publish_id,
+ const struct wpabuf *ssi);
+int wpas_nan_usd_subscribe(struct wpa_supplicant *wpa_s,
+ const char *service_name,
+ enum nan_service_protocol_type srv_proto_type,
+ const struct wpabuf *ssi,
+ struct nan_subscribe_params *params);
+void wpas_nan_usd_cancel_subscribe(struct wpa_supplicant *wpa_s,
+ int subscribe_id);
+int wpas_nan_usd_transmit(struct wpa_supplicant *wpa_s, int handle,
+ const struct wpabuf *ssi, const struct wpabuf *elems,
+ const u8 *peer_addr, u8 req_instance_id);
+void wpas_nan_usd_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
+ unsigned int freq,
+ unsigned int duration);
+void wpas_nan_usd_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
+ unsigned int freq);
+void wpas_nan_usd_tx_wait_expire(struct wpa_supplicant *wpa_s);
+int * wpas_nan_usd_all_freqs(struct wpa_supplicant *wpa_s);
+
+#endif /* NAN_USD_H */
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index a1746da..6f162f2 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -1103,15 +1103,6 @@
#endif /* CONFIG_HS20 */
}
-void wpas_notify_hs20_rx_terms_and_conditions_acceptance(
- struct wpa_supplicant *wpa_s, const char *url) {
-#ifdef CONFIG_HS20
- if (!wpa_s || !url)
- return;
-
- wpas_aidl_notify_hs20_rx_terms_and_conditions_acceptance(wpa_s, url);
-#endif /* CONFIG_HS20 */
-}
#ifdef CONFIG_MESH
@@ -1437,3 +1428,16 @@
wpas_aidl_notify_qos_policy_scs_response(wpa_s, num_scs_resp, scs_resp);
}
+
+void wpas_notify_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
+ const char *url)
+{
+#ifdef CONFIG_HS20
+ if (!wpa_s || !url)
+ return;
+
+ wpa_msg(wpa_s, MSG_INFO, HS20_T_C_ACCEPTANCE "%s", url);
+ wpas_aidl_notify_hs20_rx_terms_and_conditions_acceptance(wpa_s, url);
+ wpas_dbus_signal_hs20_t_c_acceptance(wpa_s, url);
+#endif /* CONFIG_HS20 */
+}
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index 260f439..d4656ad 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -182,8 +182,6 @@
void wpas_notify_hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s,
u8 code, u16 reauth_delay,
const char *url);
-void wpas_notify_hs20_rx_terms_and_conditions_acceptance(
- struct wpa_supplicant *wpa_s, const char *url);
void wpas_notify_dpp_config_received(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, bool conn_status_requested);
void wpas_notify_dpp_config_sent(struct wpa_supplicant *wpa_s);
@@ -232,5 +230,7 @@
unsigned int num_scs_resp, int **scs_resp);
void wpas_notify_mlo_info_change_reason(struct wpa_supplicant *wpa_s,
enum mlo_info_change_reason reason);
+void wpas_notify_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
+ const char *url);
#endif /* NOTIFY_H */
diff --git a/wpa_supplicant/offchannel.c b/wpa_supplicant/offchannel.c
index e40cf5b..9e591d7 100644
--- a/wpa_supplicant/offchannel.c
+++ b/wpa_supplicant/offchannel.c
@@ -23,12 +23,12 @@
{
struct wpa_supplicant *iface;
- if (os_memcmp(src, wpa_s->own_addr, ETH_ALEN) == 0) {
+ if (ether_addr_equal(src, wpa_s->own_addr)) {
#ifdef CONFIG_P2P
if (wpa_s->p2p_mgmt && wpa_s != wpa_s->parent &&
wpa_s->parent->ap_iface &&
- os_memcmp(wpa_s->parent->own_addr,
- wpa_s->own_addr, ETH_ALEN) == 0 &&
+ ether_addr_equal(wpa_s->parent->own_addr,
+ wpa_s->own_addr) &&
wpabuf_len(wpa_s->pending_action_tx) >= 2 &&
*wpabuf_head_u8(wpa_s->pending_action_tx) !=
WLAN_ACTION_PUBLIC) {
@@ -52,7 +52,7 @@
*/
iface = wpa_s->global->ifaces;
while (iface) {
- if (os_memcmp(src, iface->own_addr, ETH_ALEN) == 0)
+ if (ether_addr_equal(src, iface->own_addr))
break;
iface = iface->next;
}
@@ -186,7 +186,7 @@
return;
}
- if (os_memcmp(dst, wpa_s->pending_action_dst, ETH_ALEN) != 0) {
+ if (!ether_addr_equal(dst, wpa_s->pending_action_dst)) {
wpa_printf(MSG_DEBUG, "Off-channel: Ignore Action TX status - "
"unknown destination address");
return;
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index c150863..3c121c8 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -1187,7 +1187,7 @@
"group (GO Dev Addr " MACSTR ")", MAC2STR(go_dev_addr));
for (s = wpa_s->conf->ssid; s; s = s->next) {
if (s->disabled == 2 &&
- os_memcmp(go_dev_addr, s->bssid, ETH_ALEN) == 0 &&
+ ether_addr_equal(go_dev_addr, s->bssid) &&
s->ssid_len == ssid->ssid_len &&
os_memcmp(ssid->ssid, s->ssid, ssid->ssid_len) == 0)
break;
@@ -1293,8 +1293,8 @@
return;
for (i = 0; s->p2p_client_list && i < s->num_p2p_clients; i++) {
- if (os_memcmp(s->p2p_client_list + i * 2 * ETH_ALEN, addr,
- ETH_ALEN) != 0)
+ if (!ether_addr_equal(s->p2p_client_list + i * 2 * ETH_ALEN,
+ addr))
continue;
if (i == s->num_p2p_clients - 1)
@@ -1595,8 +1595,8 @@
if (result != OFFCHANNEL_SEND_ACTION_SUCCESS &&
wpa_s->pending_pd_before_join &&
- (os_memcmp(dst, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0 ||
- os_memcmp(dst, wpa_s->pending_join_iface_addr, ETH_ALEN) == 0) &&
+ (ether_addr_equal(dst, wpa_s->pending_join_dev_addr) ||
+ ether_addr_equal(dst, wpa_s->pending_join_iface_addr)) &&
wpa_s->p2p_fallback_to_go_neg) {
wpa_s->pending_pd_before_join = 0;
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No ACK for PD Req "
@@ -2937,8 +2937,8 @@
char params[20];
if (wpa_s->pending_pd_before_join &&
- (os_memcmp(peer, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0 ||
- os_memcmp(peer, wpa_s->pending_join_iface_addr, ETH_ALEN) == 0)) {
+ (ether_addr_equal(peer, wpa_s->pending_join_dev_addr) ||
+ ether_addr_equal(peer, wpa_s->pending_join_iface_addr))) {
wpa_s->pending_pd_before_join = 0;
wpa_printf(MSG_DEBUG, "P2P: Starting pending "
"join-existing-group operation");
@@ -3232,9 +3232,8 @@
" to join an active group (SSID: %s)",
MAC2STR(sa), wpa_ssid_txt(ssid, ssid_len));
if (!is_zero_ether_addr(wpa_s->p2p_auth_invite) &&
- (os_memcmp(go_dev_addr, wpa_s->p2p_auth_invite, ETH_ALEN)
- == 0 ||
- os_memcmp(sa, wpa_s->p2p_auth_invite, ETH_ALEN) == 0)) {
+ (ether_addr_equal(go_dev_addr, wpa_s->p2p_auth_invite) ||
+ ether_addr_equal(sa, wpa_s->p2p_auth_invite))) {
wpa_printf(MSG_DEBUG, "P2P: Accept previously "
"authorized invitation");
goto accept_inv;
@@ -3271,7 +3270,7 @@
}
if (!is_zero_ether_addr(wpa_s->p2p_auth_invite) &&
- os_memcmp(sa, wpa_s->p2p_auth_invite, ETH_ALEN) == 0) {
+ ether_addr_equal(sa, wpa_s->p2p_auth_invite)) {
wpa_printf(MSG_DEBUG, "P2P: Accept previously initiated "
"invitation to re-invoke a persistent group");
os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
@@ -3280,7 +3279,7 @@
for (s = wpa_s->conf->ssid; s; s = s->next) {
if (s->disabled == 2 &&
- os_memcmp(s->bssid, go_dev_addr, ETH_ALEN) == 0 &&
+ ether_addr_equal(s->bssid, go_dev_addr) &&
s->ssid_len == ssid_len &&
os_memcmp(ssid, s->ssid, ssid_len) == 0)
break;
@@ -3482,13 +3481,13 @@
return;
for (i = 0; ssid->p2p_client_list && i < ssid->num_p2p_clients; i++) {
- if (os_memcmp(ssid->p2p_client_list + i * 2 * ETH_ALEN, peer,
- ETH_ALEN) == 0)
+ if (ether_addr_equal(ssid->p2p_client_list + i * 2 * ETH_ALEN,
+ peer))
break;
}
if (i >= ssid->num_p2p_clients || !ssid->p2p_client_list) {
if (ssid->mode != WPAS_MODE_P2P_GO &&
- os_memcmp(ssid->bssid, peer, ETH_ALEN) == 0) {
+ ether_addr_equal(ssid->bssid, peer)) {
wpa_printf(MSG_DEBUG, "P2P: Remove persistent group %d "
"due to invitation result", ssid->id);
wpas_notify_network_removed(wpa_s, ssid);
@@ -4185,7 +4184,7 @@
struct wpa_supplicant *wpa_s = ctx;
for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
- if (os_memcmp(wpa_s->own_addr, interface_addr, ETH_ALEN) == 0)
+ if (ether_addr_equal(wpa_s->own_addr, interface_addr))
break;
}
if (wpa_s == NULL)
@@ -4224,7 +4223,7 @@
struct wpa_ssid *ssid = wpa_s->current_ssid;
if (ssid && (ssid->mode != WPAS_MODE_INFRA || !ssid->p2p_group))
continue;
- if (os_memcmp(wpa_s->go_dev_addr, peer_dev_addr, ETH_ALEN) == 0)
+ if (ether_addr_equal(wpa_s->go_dev_addr, peer_dev_addr))
return wpa_s;
}
@@ -4435,7 +4434,7 @@
while ((s = wpas_p2p_get_persistent(wpa_s, peer, NULL, 0))) {
if (go && ssid && ssid_len &&
s->ssid_len == ssid_len &&
- os_memcmp(go, s->bssid, ETH_ALEN) == 0 &&
+ ether_addr_equal(go, s->bssid) &&
os_memcmp(ssid, s->ssid, ssid_len) == 0)
break;
@@ -4451,8 +4450,8 @@
}
for (i = 0; i < s->num_p2p_clients; i++) {
- if (os_memcmp(s->p2p_client_list + i * 2 * ETH_ALEN,
- peer, ETH_ALEN) != 0)
+ if (!ether_addr_equal(s->p2p_client_list +
+ i * 2 * ETH_ALEN, peer))
continue;
os_memmove(s->p2p_client_list + i * 2 * ETH_ALEN,
@@ -4606,7 +4605,7 @@
break;
if (s && s->ssid_len == stale->ssid_len &&
- os_memcmp(stale->bssid, s->bssid, ETH_ALEN) == 0 &&
+ ether_addr_equal(stale->bssid, s->bssid) &&
os_memcmp(stale->ssid, s->ssid, s->ssid_len) == 0)
break;
@@ -4622,9 +4621,8 @@
size_t i;
for (i = 0; i < stale->num_p2p_clients; i++) {
- if (os_memcmp(stale->p2p_client_list +
- i * ETH_ALEN,
- dev, ETH_ALEN) == 0) {
+ if (ether_addr_equal(stale->p2p_client_list +
+ i * ETH_ALEN, dev)) {
os_memmove(stale->p2p_client_list +
i * ETH_ALEN,
stale->p2p_client_list +
@@ -5474,8 +5472,8 @@
p2p_get_interface_addr(wpa_s->global->p2p,
wpa_s->pending_join_dev_addr,
iface_addr) == 0 &&
- os_memcmp(iface_addr, wpa_s->pending_join_dev_addr, ETH_ALEN) != 0
- && !wpa_bss_get_bssid(wpa_s, wpa_s->pending_join_iface_addr)) {
+ !ether_addr_equal(iface_addr, wpa_s->pending_join_dev_addr) &&
+ !wpa_bss_get_bssid(wpa_s, wpa_s->pending_join_iface_addr)) {
wpa_printf(MSG_DEBUG, "P2P: Overwrite pending interface "
"address for join from " MACSTR " to " MACSTR
" based on newly discovered P2P peer entry",
@@ -5515,10 +5513,9 @@
wpa_ssid_txt(bss->ssid, bss->ssid_len));
if (p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len,
dev_addr) == 0 &&
- os_memcmp(wpa_s->pending_join_dev_addr,
- wpa_s->pending_join_iface_addr, ETH_ALEN) == 0 &&
- os_memcmp(dev_addr, wpa_s->pending_join_dev_addr,
- ETH_ALEN) != 0) {
+ ether_addr_equal(wpa_s->pending_join_dev_addr,
+ wpa_s->pending_join_iface_addr) &&
+ !ether_addr_equal(dev_addr, wpa_s->pending_join_dev_addr)) {
wpa_printf(MSG_DEBUG,
"P2P: Update target GO device address based on BSS entry: " MACSTR " (was " MACSTR ")",
MAC2STR(dev_addr),
@@ -7504,9 +7501,10 @@
}
-static void wpas_p2p_clear_pending_action_tx(struct wpa_supplicant *wpa_s)
+static void wpas_p2p_clear_pending_action_tx(struct wpa_supplicant *wpa_s,
+ bool force)
{
- if (!offchannel_pending_action_tx(wpa_s))
+ if (!offchannel_pending_action_tx(wpa_s) && !force)
return;
if (wpa_s->p2p_send_action_work) {
@@ -7516,6 +7514,8 @@
offchannel_send_action_done(wpa_s);
}
+ if (!offchannel_pending_action_tx(wpa_s))
+ return;
wpa_printf(MSG_DEBUG, "P2P: Drop pending Action TX due to new "
"operation request");
offchannel_clear_pending_action_tx(wpa_s);
@@ -7529,7 +7529,7 @@
u8 seek_cnt, const char **seek_string, int freq,
bool include_6ghz)
{
- wpas_p2p_clear_pending_action_tx(wpa_s);
+ wpas_p2p_clear_pending_action_tx(wpa_s, false);
wpa_s->global->p2p_long_listen = 0;
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL ||
@@ -7575,7 +7575,7 @@
static void wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s)
{
- wpas_p2p_clear_pending_action_tx(wpa_s);
+ wpas_p2p_clear_pending_action_tx(wpa_s, true);
wpa_s->global->p2p_long_listen = 0;
eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
@@ -7620,7 +7620,7 @@
}
wpa_supplicant_cancel_sched_scan(wpa_s);
- wpas_p2p_clear_pending_action_tx(wpa_s);
+ wpas_p2p_clear_pending_action_tx(wpa_s, false);
if (timeout == 0) {
/*
@@ -8740,13 +8740,13 @@
return s;
continue;
}
- if (os_memcmp(s->bssid, addr, ETH_ALEN) == 0)
+ if (ether_addr_equal(s->bssid, addr))
return s; /* peer is GO in the persistent group */
if (s->mode != WPAS_MODE_P2P_GO || s->p2p_client_list == NULL)
continue;
for (i = 0; i < s->num_p2p_clients; i++) {
- if (os_memcmp(s->p2p_client_list + i * 2 * ETH_ALEN,
- addr, ETH_ALEN) == 0)
+ if (ether_addr_equal(s->p2p_client_list +
+ i * 2 * ETH_ALEN, addr))
return s; /* peer is P2P client in persistent
* group */
}
@@ -8888,9 +8888,9 @@
dl_list_for_each_safe(psk, tmp, &s->psk_list, struct psk_list_entry,
list) {
if ((iface_addr && !psk->p2p &&
- os_memcmp(addr, psk->addr, ETH_ALEN) == 0) ||
+ ether_addr_equal(addr, psk->addr)) ||
(!iface_addr && psk->p2p &&
- os_memcmp(addr, psk->addr, ETH_ALEN) == 0)) {
+ ether_addr_equal(addr, psk->addr))) {
wpa_dbg(wpa_s, MSG_DEBUG,
"P2P: Remove persistent group PSK list entry for "
MACSTR " p2p=%u",
@@ -9029,9 +9029,9 @@
prev = NULL;
psk = hapd->conf->ssid.wpa_psk;
while (psk) {
- if ((iface_addr && os_memcmp(peer, psk->addr, ETH_ALEN) == 0) ||
+ if ((iface_addr && ether_addr_equal(peer, psk->addr)) ||
(!iface_addr &&
- os_memcmp(peer, psk->p2p_dev_addr, ETH_ALEN) == 0)) {
+ ether_addr_equal(peer, psk->p2p_dev_addr))) {
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Remove operating group PSK entry for "
MACSTR " iface_addr=%d",
MAC2STR(peer), iface_addr);
@@ -9885,6 +9885,7 @@
os_memset(&csa_settings, 0, sizeof(csa_settings));
csa_settings.cs_count = P2P_GO_CSA_COUNT;
csa_settings.block_tx = P2P_GO_CSA_BLOCK_TX;
+ csa_settings.link_id = -1;
csa_settings.freq_params.freq = params.freq;
csa_settings.freq_params.sec_channel_offset = conf->secondary_channel;
csa_settings.freq_params.ht_enabled = conf->ieee80211n;
diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c
index edecfde..2e65cf0 100644
--- a/wpa_supplicant/pasn_supplicant.c
+++ b/wpa_supplicant/pasn_supplicant.c
@@ -320,7 +320,7 @@
return -1;
}
- if (os_memcmp(entry->own_addr, own_addr, ETH_ALEN) != 0) {
+ if (!ether_addr_equal(entry->own_addr, own_addr)) {
wpa_printf(MSG_DEBUG,
"PASN: own addr " MACSTR " and PTKSA entry own addr "
MACSTR " differ",
@@ -352,7 +352,7 @@
while (wpa_s->pasn_count < pasn_params->num_peers) {
peer = &pasn_params->peer[wpa_s->pasn_count];
- if (os_memcmp(wpa_s->bssid, peer->peer_addr, ETH_ALEN) == 0) {
+ if (ether_addr_equal(wpa_s->bssid, peer->peer_addr)) {
wpa_printf(MSG_DEBUG,
"PASN: Associated peer is not expected");
peer->status = PASN_STATUS_FAILURE;
@@ -426,6 +426,7 @@
}
+#ifdef CONFIG_FILS
static void wpas_pasn_initiate_eapol(struct pasn_data *pasn,
struct wpa_ssid *ssid)
{
@@ -443,6 +444,7 @@
eapol_sm_notify_config(pasn->eapol, &ssid->eap, &eapol_conf);
}
+#endif /* CONFIG_FILS */
static void wpas_pasn_reset(struct wpa_supplicant *wpa_s)
@@ -466,13 +468,13 @@
struct wpa_ie_data rsne_data;
int ret;
- if (os_memcmp(wpa_s->bssid, peer_addr, ETH_ALEN) == 0) {
+ if (ether_addr_equal(wpa_s->bssid, peer_addr)) {
wpa_printf(MSG_DEBUG,
"PASN: Not doing authentication with current BSS");
return NULL;
}
- bss = wpa_bss_get_bssid(wpa_s, peer_addr);
+ bss = wpa_bss_get_bssid_latest(wpa_s, peer_addr);
if (!bss) {
wpa_printf(MSG_DEBUG, "PASN: BSS not found");
return NULL;
@@ -509,8 +511,10 @@
struct wpa_ssid *ssid;
struct wpa_bss *bss;
const u8 *rsne, *rsnxe;
+#ifdef CONFIG_FILS
const u8 *indic;
u16 fils_info;
+#endif /* CONFIG_FILS */
u16 capab = 0;
bool derive_kdk;
int ret;
@@ -921,7 +925,7 @@
struct ieee80211_mgmt *deauth;
int ret;
- if (os_memcmp(wpa_s->bssid, peer_addr, ETH_ALEN) == 0) {
+ if (ether_addr_equal(wpa_s->bssid, peer_addr)) {
wpa_printf(MSG_DEBUG,
"PASN: Cannot deauthenticate from current BSS");
return -1;
diff --git a/wpa_supplicant/robust_av.c b/wpa_supplicant/robust_av.c
index 58edd9b..658103d 100644
--- a/wpa_supplicant/robust_av.c
+++ b/wpa_supplicant/robust_av.c
@@ -665,17 +665,91 @@
}
+/* Element ID Extension(1) + Request Type(1) + User Priority Control(2) +
+ * Stream Timeout(4) */
+#define MSCS_DESCRIPTOR_FIXED_LEN 8
+
+static void wpas_parse_mscs_resp(struct wpa_supplicant *wpa_s,
+ u16 status, const u8 *bssid,
+ const u8 *mscs_desc_ie)
+{
+ struct robust_av_data robust_av;
+ const u8 *pos;
+
+ /* The MSCS Descriptor element is optional in the MSCS Response frame */
+ if (!mscs_desc_ie)
+ goto event_mscs_result;
+
+ if (mscs_desc_ie[1] < MSCS_DESCRIPTOR_FIXED_LEN) {
+ wpa_printf(MSG_INFO,
+ "MSCS: Drop received frame: invalid MSCS Descriptor element length: %d",
+ mscs_desc_ie[1]);
+ return;
+ }
+
+ os_memset(&robust_av, 0, sizeof(struct robust_av_data));
+
+ /* Skip Element ID, Length, and Element ID Extension */
+ pos = &mscs_desc_ie[3];
+
+ robust_av.request_type = *pos++;
+
+ switch (robust_av.request_type) {
+ case SCS_REQ_CHANGE:
+ /*
+ * Inform the suggested set of parameters that could be accepted
+ * by the AP in response to a subsequent request by the station.
+ */
+ robust_av.up_bitmap = *pos++;
+ robust_av.up_limit = *pos++ & 0x07;
+ robust_av.stream_timeout = WPA_GET_LE32(pos);
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
+ " status_code=%u change up_bitmap=%u up_limit=%u stream_timeout=%u",
+ MAC2STR(bssid), status, robust_av.up_bitmap,
+ robust_av.up_limit, robust_av.stream_timeout);
+ wpa_s->mscs_setup_done = false;
+ return;
+ case SCS_REQ_ADD:
+ /*
+ * This type is used in (Re)Association Response frame MSCS
+ * Descriptor element if no change is required.
+ */
+ break;
+ default:
+ wpa_printf(MSG_INFO,
+ "MSCS: Drop received frame with unknown Request Type: %u",
+ robust_av.request_type);
+ return;
+ }
+
+event_mscs_result:
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
+ " status_code=%u", MAC2STR(bssid), status);
+ wpa_s->mscs_setup_done = status == WLAN_STATUS_SUCCESS;
+}
+
+
void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s,
const u8 *src, const u8 *buf, size_t len)
{
u8 dialog_token;
u16 status_code;
+ const u8 *mscs_desc_ie;
if (len < 3)
return;
dialog_token = *buf++;
- if (dialog_token != wpa_s->robust_av.dialog_token) {
+ len--;
+
+ /* AP sets dialog token to 0 for unsolicited response */
+ if (!dialog_token && !wpa_s->mscs_setup_done) {
+ wpa_printf(MSG_INFO,
+ "MSCS: Drop unsolicited received frame: inactive");
+ return;
+ }
+
+ if (dialog_token && dialog_token != wpa_s->robust_av.dialog_token) {
wpa_printf(MSG_INFO,
"MSCS: Drop received frame due to dialog token mismatch: received:%u expected:%u",
dialog_token, wpa_s->robust_av.dialog_token);
@@ -683,9 +757,11 @@
}
status_code = WPA_GET_LE16(buf);
- wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
- " status_code=%u", MAC2STR(src), status_code);
- wpa_s->mscs_setup_done = status_code == WLAN_STATUS_SUCCESS;
+ buf += 2;
+ len -= 2;
+
+ mscs_desc_ie = get_ie_ext(buf, len, WLAN_EID_EXT_MSCS_DESCRIPTOR);
+ wpas_parse_mscs_resp(wpa_s, status_code, src, mscs_desc_ie);
}
@@ -701,21 +777,19 @@
return;
mscs_desc_ie = get_ie_ext(ies, ies_len, WLAN_EID_EXT_MSCS_DESCRIPTOR);
- if (!mscs_desc_ie || mscs_desc_ie[1] <= 8)
+ if (!mscs_desc_ie || mscs_desc_ie[1] <= MSCS_DESCRIPTOR_FIXED_LEN)
return;
- /* Subelements start after (ie_id(1) + ie_len(1) + ext_id(1) +
- * request type(1) + upc(2) + stream timeout(4) =) 10.
- */
- mscs_status = get_ie(&mscs_desc_ie[10], mscs_desc_ie[1] - 8,
+ /* Subelements start after element header and fixed fields */
+ mscs_status = get_ie(&mscs_desc_ie[2 + MSCS_DESCRIPTOR_FIXED_LEN],
+ mscs_desc_ie[1] - MSCS_DESCRIPTOR_FIXED_LEN,
MCSC_SUBELEM_STATUS);
if (!mscs_status || mscs_status[1] < 2)
return;
status = WPA_GET_LE16(mscs_status + 2);
- wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
- " status_code=%u", MAC2STR(bssid), status);
- wpa_s->mscs_setup_done = status == WLAN_STATUS_SUCCESS;
+
+ wpas_parse_mscs_resp(wpa_s, status, bssid, mscs_desc_ie);
}
diff --git a/wpa_supplicant/rrm.c b/wpa_supplicant/rrm.c
index 8e51717..7ce854b 100644
--- a/wpa_supplicant/rrm.c
+++ b/wpa_supplicant/rrm.c
@@ -772,6 +772,7 @@
static int wpas_beacon_rep_add_frame_body(struct bitfield *eids,
+ struct bitfield *ext_eids,
enum beacon_report_detail detail,
struct wpa_bss *bss, u8 *buf,
size_t buf_len, const u8 **ies_buf,
@@ -828,7 +829,9 @@
*/
while (ies_len > 2 && 2U + ies[1] <= ies_len && rem_len > 0) {
if (detail == BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS ||
- (eids && bitfield_is_set(eids, ies[0]))) {
+ (eids && bitfield_is_set(eids, ies[0])) ||
+ (ext_eids && ies[0] == WLAN_EID_EXTENSION && ies[1] &&
+ bitfield_is_set(ext_eids, ies[2]))) {
u8 elen = ies[1];
if (2 + elen > buf + buf_len - pos ||
@@ -876,7 +879,8 @@
os_memcpy(buf, rep, sizeof(*rep));
- ret = wpas_beacon_rep_add_frame_body(data->eids, data->report_detail,
+ ret = wpas_beacon_rep_add_frame_body(data->eids, data->ext_eids,
+ data->report_detail,
bss, buf + sizeof(*rep),
14 + *ie_len, ie, ie_len,
idx == 0);
@@ -932,8 +936,8 @@
struct rrm_measurement_beacon_report rep;
u8 idx = 0;
- if (os_memcmp(data->bssid, broadcast_ether_addr, ETH_ALEN) != 0 &&
- os_memcmp(data->bssid, bss->bssid, ETH_ALEN) != 0)
+ if (!ether_addr_equal(data->bssid, broadcast_ether_addr) &&
+ !ether_addr_equal(data->bssid, bss->bssid))
return 0;
if (data->ssid_len &&
@@ -1043,6 +1047,7 @@
struct beacon_rep_data *data,
u8 sid, u8 slen, const u8 *subelem)
{
+ struct bitfield *eids;
u8 report_info, i;
switch (sid) {
@@ -1096,6 +1101,7 @@
break;
case WLAN_BEACON_REQUEST_SUBELEM_REQUEST:
+ case WLAN_BEACON_REQUEST_SUBELEM_EXT_REQUEST:
if (data->report_detail !=
BEACON_REPORT_DETAIL_REQUESTED_ONLY) {
wpa_printf(MSG_DEBUG,
@@ -1111,20 +1117,46 @@
return -1;
}
- if (data->eids) {
+ if (sid == WLAN_BEACON_REQUEST_SUBELEM_EXT_REQUEST) {
+ if (slen < 2) {
+ wpa_printf(MSG_DEBUG,
+ "Invalid extended request");
+ return -1;
+ }
+ if (subelem[0] != WLAN_EID_EXTENSION) {
+ wpa_printf(MSG_DEBUG,
+ "Skip unknown Requested Element ID %u in Extended Request subelement",
+ subelem[0]);
+ break;
+ }
+
+ /* Skip the Requested Element ID field */
+ subelem++;
+ slen--;
+ }
+
+ if ((sid == WLAN_BEACON_REQUEST_SUBELEM_REQUEST &&
+ data->eids) ||
+ (sid == WLAN_BEACON_REQUEST_SUBELEM_EXT_REQUEST &&
+ data->ext_eids)) {
wpa_printf(MSG_DEBUG,
- "Beacon Request: Request subelement appears more than once");
+ "Beacon Request: Request sub elements appear more than once");
return -1;
}
- data->eids = bitfield_alloc(255);
- if (!data->eids) {
+ eids = bitfield_alloc(255);
+ if (!eids) {
wpa_printf(MSG_DEBUG, "Failed to allocate EIDs bitmap");
return -1;
}
+ if (sid == WLAN_BEACON_REQUEST_SUBELEM_REQUEST)
+ data->eids = eids;
+ else
+ data->ext_eids = eids;
+
for (i = 0; i < slen; i++)
- bitfield_set(data->eids, subelem[i]);
+ bitfield_set(eids, subelem[i]);
break;
case WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL:
/* Skip - it will be processed when freqs are added */
@@ -1480,6 +1512,29 @@
}
+static bool wpas_beacon_rep_scan_match(struct wpa_supplicant *wpa_s,
+ const u8 *bssid)
+{
+ u8 i;
+
+ if (!wpa_s->valid_links)
+ return ether_addr_equal(wpa_s->current_bss->bssid, bssid);
+
+ for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+ if (!(wpa_s->valid_links & BIT(i)))
+ continue;
+
+ if (ether_addr_equal(wpa_s->links[i].bssid, bssid))
+ return true;
+ }
+
+ wpa_printf(MSG_DEBUG, "RRM: MLD: no match for TSF BSSID=" MACSTR,
+ MAC2STR(bssid));
+
+ return false;
+}
+
+
int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res,
struct scan_info *info)
@@ -1501,8 +1556,7 @@
MAC2STR(info->scan_start_tsf_bssid),
MAC2STR(wpa_s->current_bss->bssid));
if ((wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT) &&
- os_memcmp(info->scan_start_tsf_bssid, wpa_s->current_bss->bssid,
- ETH_ALEN) != 0) {
+ !wpas_beacon_rep_scan_match(wpa_s, info->scan_start_tsf_bssid)) {
wpa_printf(MSG_DEBUG,
"RRM: Ignore scan results due to mismatching TSF BSSID");
goto out;
@@ -1517,8 +1571,8 @@
if ((wpa_s->drv_rrm_flags &
WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT) &&
- os_memcmp(scan_res->res[i]->tsf_bssid,
- wpa_s->current_bss->bssid, ETH_ALEN) != 0) {
+ !wpas_beacon_rep_scan_match(wpa_s,
+ scan_res->res[i]->tsf_bssid)) {
wpa_printf(MSG_DEBUG,
"RRM: Ignore scan result for " MACSTR
" due to mismatching TSF BSSID" MACSTR,
@@ -1587,6 +1641,7 @@
eloop_cancel_timeout(wpas_rrm_scan_timeout, wpa_s, NULL);
bitfield_free(data->eids);
+ bitfield_free(data->ext_eids);
os_free(data->scan_params.freqs);
os_memset(data, 0, sizeof(*data));
}
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index bab6a23..6e6f05d 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -261,8 +261,10 @@
wpa_s->scan_res_handler = NULL;
}
+#ifndef CONFIG_NO_RRM
if (wpa_s->beacon_rep_data.token)
wpas_rrm_refuse_request(wpa_s);
+#endif /* CONFIG_NO_RRM */
return;
}
@@ -2253,7 +2255,6 @@
static int wpas_channel_width_tx_pwr(const u8 *ies, size_t ies_len,
enum chan_width cw)
{
-#define MIN(a, b) (a < b ? a : b)
int offset = wpas_channel_width_offset(cw);
const struct element *elem;
int max_tx_power = TX_POWER_NO_CONSTRAINT, tx_pwr = 0;
@@ -2329,7 +2330,6 @@
}
return max_tx_power;
-#undef MIN
}
@@ -2371,7 +2371,6 @@
* better. */
static int wpa_scan_result_compar(const void *a, const void *b)
{
-#define MIN(a,b) a < b ? a : b
struct wpa_scan_res **_wa = (void *) a;
struct wpa_scan_res **_wb = (void *) b;
struct wpa_scan_res *wa = *_wa;
@@ -2379,6 +2378,7 @@
int wpa_a, wpa_b;
int snr_a, snr_b, snr_a_full, snr_b_full;
size_t ies_len;
+ const u8 *rsne_a, *rsne_b;
/* WPA/WPA2 support preferred */
wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL ||
@@ -2422,6 +2422,32 @@
snr_b = snr_b_full = wb->level;
}
+ /* If SNR of a SAE BSS is good or at least as high as the PSK BSS,
+ * prefer SAE over PSK for mixed WPA3-Personal transition mode and
+ * WPA2-Personal deployments */
+ rsne_a = wpa_scan_get_ie(wa, WLAN_EID_RSN);
+ rsne_b = wpa_scan_get_ie(wb, WLAN_EID_RSN);
+ if (rsne_a && rsne_b) {
+ struct wpa_ie_data data;
+ bool psk_a = false, psk_b = false, sae_a = false, sae_b = false;
+
+ if (wpa_parse_wpa_ie_rsn(rsne_a, 2 + rsne_a[1], &data) == 0) {
+ psk_a = wpa_key_mgmt_wpa_psk_no_sae(data.key_mgmt);
+ sae_a = wpa_key_mgmt_sae(data.key_mgmt);
+ }
+ if (wpa_parse_wpa_ie_rsn(rsne_b, 2 + rsne_b[1], &data) == 0) {
+ psk_b = wpa_key_mgmt_wpa_psk_no_sae(data.key_mgmt);
+ sae_b = wpa_key_mgmt_sae(data.key_mgmt);
+ }
+
+ if (sae_a && !sae_b && psk_b &&
+ (snr_a >= GREAT_SNR || snr_a >= snr_b))
+ return -1;
+ if (sae_b && !sae_a && psk_a &&
+ (snr_b >= GREAT_SNR || snr_b >= snr_a))
+ return 1;
+ }
+
/* If SNR is close, decide by max rate or frequency band. For cases
* involving the 6 GHz band, use the throughput estimate irrespective
* of the SNR difference since the LPI/VLP rules may result in
@@ -2448,7 +2474,6 @@
if (snr_b_full == snr_a_full)
return wb->qual - wa->qual;
return snr_b_full - snr_a_full;
-#undef MIN
}
@@ -2573,8 +2598,7 @@
return 1;
for (i = 0; i < wpa_s->bssid_filter_count; i++) {
- if (os_memcmp(wpa_s->bssid_filter + i * ETH_ALEN, bssid,
- ETH_ALEN) == 0)
+ if (ether_addr_equal(wpa_s->bssid_filter + i * ETH_ALEN, bssid))
return 1;
}
@@ -2878,6 +2902,7 @@
* been taken into account.
*/
int adjusted_snr;
+ bool ht40 = false, vht80 = false, vht160 = false;
/* Limit based on estimated SNR */
if (rate > 1 * 2 && snr < 1)
@@ -2933,11 +2958,14 @@
}
}
+ ie = get_ie(ies, ies_len, WLAN_EID_HT_OPERATION);
+ if (ie && ie[1] >= 2 &&
+ (ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK))
+ ht40 = true;
+
if (hw_mode &&
(hw_mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
- ie = get_ie(ies, ies_len, WLAN_EID_HT_OPERATION);
- if (ie && ie[1] >= 2 &&
- (ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) {
+ if (ht40) {
*max_cw = CHAN_WIDTH_40;
adjusted_snr = snr +
wpas_channel_width_rssi_bump(ies, ies_len,
@@ -2948,22 +2976,36 @@
}
}
+ /* Determine VHT BSS bandwidth based on IEEE Std 802.11-2020,
+ * Table 11-23 (VHT BSS bandwidth) */
+ ie = get_ie(ies, ies_len, WLAN_EID_VHT_OPERATION);
+ if (ie && ie[1] >= 3) {
+ u8 cw = ie[2] & VHT_OPMODE_CHANNEL_WIDTH_MASK;
+ u8 seg0 = ie[3];
+ u8 seg1 = ie[4];
+
+ if (cw)
+ vht80 = true;
+ if (cw == 2 ||
+ (cw == 3 && (seg1 > 0 && abs(seg1 - seg0) == 16)))
+ vht160 = true;
+ if (cw == 1 &&
+ ((seg1 > 0 && abs(seg1 - seg0) == 8) ||
+ (seg1 > 0 && abs(seg1 - seg0) == 16)))
+ vht160 = true;
+ }
+
if (hw_mode && hw_mode->vht_capab) {
/* Use +1 to assume VHT is always faster than HT */
ie = get_ie(ies, ies_len, WLAN_EID_VHT_CAP);
if (ie) {
- bool vht80 = false, vht160 = false;
-
if (*max_cw == CHAN_WIDTH_UNKNOWN)
*max_cw = CHAN_WIDTH_20;
tmp = max_ht20_rate(snr, true) + 1;
if (tmp > est)
est = tmp;
- ie = get_ie(ies, ies_len, WLAN_EID_HT_OPERATION);
- if (ie && ie[1] >= 2 &&
- (ie[3] &
- HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) {
+ if (ht40) {
*max_cw = CHAN_WIDTH_40;
adjusted_snr = snr +
wpas_channel_width_rssi_bump(
@@ -2973,26 +3015,6 @@
est = tmp;
}
- /* Determine VHT BSS bandwidth based on IEEE Std
- * 802.11-2020, Table 11-23 (VHT BSs bandwidth) */
- ie = get_ie(ies, ies_len, WLAN_EID_VHT_OPERATION);
- if (ie && ie[1] >= 3) {
- u8 cw = ie[2] & VHT_OPMODE_CHANNEL_WIDTH_MASK;
- u8 seg0 = ie[3];
- u8 seg1 = ie[4];
-
- if (cw)
- vht80 = true;
- if (cw == 2 ||
- (cw == 3 &&
- (seg1 > 0 && abs(seg1 - seg0) == 16)))
- vht160 = true;
- if (cw == 1 &&
- ((seg1 > 0 && abs(seg1 - seg0) == 8) ||
- (seg1 > 0 && abs(seg1 - seg0) == 16)))
- vht160 = true;
- }
-
if (vht80) {
*max_cw = CHAN_WIDTH_80;
adjusted_snr = snr +
@@ -3052,9 +3074,10 @@
cw = he->he_phy_capab_info[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
own_he->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX];
- if (cw &
- (IS_2P4GHZ(freq) ? HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G :
- HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)) {
+ if ((cw &
+ (IS_2P4GHZ(freq) ?
+ HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G :
+ HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)) && ht40) {
if (*max_cw == CHAN_WIDTH_UNKNOWN ||
*max_cw < CHAN_WIDTH_40)
*max_cw = CHAN_WIDTH_40;
@@ -3067,7 +3090,8 @@
}
if (!IS_2P4GHZ(freq) &&
- (cw & HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)) {
+ (cw & HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G) &&
+ (!IS_5GHZ(freq) || vht80)) {
if (*max_cw == CHAN_WIDTH_UNKNOWN ||
*max_cw < CHAN_WIDTH_80)
*max_cw = CHAN_WIDTH_80;
@@ -3081,7 +3105,8 @@
if (!IS_2P4GHZ(freq) &&
(cw & (HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
- HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G))) {
+ HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)) &&
+ (!IS_5GHZ(freq) || vht160)) {
if (*max_cw == CHAN_WIDTH_UNKNOWN ||
*max_cw < CHAN_WIDTH_160)
*max_cw = CHAN_WIDTH_160;
diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h
index f1739fa..8402e74 100644
--- a/wpa_supplicant/scan.h
+++ b/wpa_supplicant/scan.h
@@ -38,9 +38,6 @@
*/
#define TX_POWER_NO_CONSTRAINT 64
-#define IS_2P4GHZ(n) (n >= 2412 && n <= 2484)
-#define IS_5GHZ(n) (n > 4000 && n < 5895)
-
int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s);
void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec);
int wpa_supplicant_delayed_sched_scan(struct wpa_supplicant *wpa_s,
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index df2c68f..b8f7c65 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -1,6 +1,6 @@
/*
* wpa_supplicant - SME
- * Copyright (c) 2009-2014, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2024, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -28,6 +28,7 @@
#include "p2p_supplicant.h"
#include "notify.h"
#include "bss.h"
+#include "bssid_ignore.h"
#include "scan.h"
#include "sme.h"
#include "hs20_supplicant.h"
@@ -165,7 +166,7 @@
}
if (reuse && wpa_s->sme.sae.tmp &&
- os_memcmp(addr, wpa_s->sme.sae.tmp->bssid, ETH_ALEN) == 0) {
+ ether_addr_equal(addr, wpa_s->sme.sae.tmp->bssid)) {
wpa_printf(MSG_DEBUG,
"SAE: Reuse previously generated PWE on a retry with the same AP");
use_pt = wpa_s->sme.sae.h2e;
@@ -242,7 +243,7 @@
wpa_s->sme.sae_rejected_groups, NULL) < 0)
goto fail;
if (!use_pt &&
- sae_prepare_commit(wpa_s->own_addr, bssid,
+ sae_prepare_commit(wpa_s->own_addr, addr,
(u8 *) password, os_strlen(password),
&wpa_s->sme.sae) < 0) {
wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
@@ -378,220 +379,6 @@
}
-static void wpas_process_tbtt_info(struct wpa_supplicant *wpa_s, const u8 *data)
-{
- struct wpa_bss *neigh_bss;
- const u8 *bssid;
- u8 bss_params;
- u8 link_id;
-
- /* TBTT Information field
- * Neighbor AP TBTT Offset[1]
- * BSSID[6]
- * Short SSID[4]
- * BSS parameters[1]
- * 20 MHz PSD[1]
- * MLD Parameters[3]
- * B0..B7: AP MLD ID
- * B7..B11: Link ID
- * B12..B19: BSS Parameters Change Count
- * B20: All Updates Included
- * B21: Disabled Link Indication */
-
- bssid = data + 1;
- bss_params = data[1 + ETH_ALEN + 4];
-
- data += 13; /* MLD Parameters */
- link_id = *(data + 1) & 0xF;
-
- wpa_dbg(wpa_s, MSG_DEBUG,
- "MLD: mld ID=%u, link ID=%u, bssid=" MACSTR ", bss_params=0x%x",
- *data, link_id, MAC2STR(bssid), bss_params);
-
- if (*data) {
- wpa_printf(MSG_DEBUG, "MLD: Reported link not part of MLD");
- return;
- }
-
- neigh_bss = wpa_bss_get_bssid(wpa_s, bssid);
- if (!neigh_bss) {
- wpa_printf(MSG_DEBUG, "MLD: Neighbor not found in scan");
- return;
- }
-
- if (!((bss_params & RNR_BSS_PARAM_SAME_SSID) &&
- (bss_params & RNR_BSS_PARAM_CO_LOCATED)) &&
- !wpa_scan_res_match(wpa_s, 0, neigh_bss, wpa_s->current_ssid,
- 1, 0)) {
- wpa_printf(MSG_DEBUG,
- "MLD: Neighbor doesn't match current SSID - skip link");
- return;
- }
-
- wpa_s->valid_links |= BIT(link_id);
- os_memcpy(wpa_s->links[link_id].bssid, bssid, ETH_ALEN);
- wpa_s->links[link_id].freq = neigh_bss->freq;
-}
-
-
-static void wpas_process_rnr(struct wpa_supplicant *wpa_s, const u8 *pos,
- size_t rnr_ie_len)
-{
- while (rnr_ie_len > sizeof(struct ieee80211_neighbor_ap_info)) {
- const struct ieee80211_neighbor_ap_info *ap_info =
- (const struct ieee80211_neighbor_ap_info *) pos;
- /* The first TBTT Information field */
- const u8 *data = ap_info->data;
- u8 tbtt_count;
- size_t len;
- int tbtt_i;
-
- if (rnr_ie_len < sizeof(struct ieee80211_neighbor_ap_info))
- break;
-
- tbtt_count = (ap_info->tbtt_info_hdr >> 4) + 1;
- len = sizeof(struct ieee80211_neighbor_ap_info) +
- ap_info->tbtt_info_len * tbtt_count;
-
- wpa_printf(MSG_DEBUG, "MLD: op_class=%u, channel=%u",
- ap_info->op_class, ap_info->channel);
-
- if (len > rnr_ie_len)
- break;
-
- if (ap_info->tbtt_info_len < 16) {
- rnr_ie_len -= len;
- pos += len;
- continue;
- }
-
- for (tbtt_i = 0; tbtt_i < tbtt_count; tbtt_i++) {
- wpas_process_tbtt_info(wpa_s, data);
- data += ap_info->tbtt_info_len;
- }
-
- rnr_ie_len -= len;
- pos += len;
- }
-}
-
-
-static bool wpas_ml_element(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
- struct wpa_ssid *ssid)
-{
- struct wpabuf *mlbuf;
- const u8 *rnr_ie, *rsn_ie;
- struct wpa_ie_data ie;
- u8 ml_ie_len;
- const struct ieee80211_eht_ml *eht_ml;
- const struct eht_ml_basic_common_info *ml_basic_common_info;
- u8 i;
- const u16 control =
- host_to_le16(MULTI_LINK_CONTROL_TYPE_BASIC |
- BASIC_MULTI_LINK_CTRL_PRES_LINK_ID |
- BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT |
- BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA);
- bool ret = false;
- int rnr_idx;
-
- if (!(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO))
- return false;
-
- mlbuf = wpa_bss_defrag_mle(bss, MULTI_LINK_CONTROL_TYPE_BASIC);
- if (!mlbuf) {
- wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No ML element");
- return false;
- }
-
- rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
- if (!rsn_ie || wpa_parse_wpa_ie(rsn_ie, 2 + rsn_ie[1], &ie)) {
- wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RSN element");
- goto out;
- }
-
- if (!(ie.capabilities & WPA_CAPABILITY_MFPC) ||
- wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- "MLD: No management frame protection");
- goto out;
- }
-
- ie.key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK |
- WPA_KEY_MGMT_PSK_SHA256);
- if (!(ie.key_mgmt & ssid->key_mgmt)) {
- wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No valid key management");
- goto out;
- }
-
- ml_ie_len = wpabuf_len(mlbuf);
-
- /* control + common info len + MLD address + MLD link information */
- if (ml_ie_len < 2 + 1 + ETH_ALEN + 1)
- goto out;
-
- eht_ml = wpabuf_head(mlbuf);
- if ((eht_ml->ml_control & control) != control) {
- wpa_printf(MSG_DEBUG, "MLD: Unexpected ML element control=0x%x",
- eht_ml->ml_control);
- goto out;
- }
-
- ml_basic_common_info =
- (const struct eht_ml_basic_common_info *) eht_ml->variable;
-
- /* common info length should be valid (self, mld_addr, link_id) */
- if (ml_basic_common_info->len < 1 + ETH_ALEN + 1)
- goto out;
-
- /* get the MLD address and MLD link ID */
- os_memcpy(wpa_s->ap_mld_addr, ml_basic_common_info->mld_addr,
- ETH_ALEN);
- wpa_s->mlo_assoc_link_id = ml_basic_common_info->variable[0] &
- EHT_ML_LINK_ID_MSK;
-
- os_memcpy(wpa_s->links[wpa_s->mlo_assoc_link_id].bssid, bss->bssid,
- ETH_ALEN);
- wpa_s->links[wpa_s->mlo_assoc_link_id].freq = bss->freq;
-
- wpa_printf(MSG_DEBUG, "MLD: address=" MACSTR ", link ID=%u",
- MAC2STR(wpa_s->ap_mld_addr), wpa_s->mlo_assoc_link_id);
-
- wpa_s->valid_links = BIT(wpa_s->mlo_assoc_link_id);
-
- ret = true;
-
- /* Process all Reduced Neighbor Report elements */
- for (rnr_idx = 1; ; rnr_idx++) {
- rnr_ie = wpa_bss_get_ie_nth(bss,
- WLAN_EID_REDUCED_NEIGHBOR_REPORT,
- rnr_idx);
- if (!rnr_ie) {
- if (rnr_idx == 0) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- "MLD: No RNR element");
- goto out;
- }
- break;
- }
- wpas_process_rnr(wpa_s, rnr_ie + 2, rnr_ie[1]);
- }
-
- wpa_printf(MSG_DEBUG, "MLD: valid_links=0x%x", wpa_s->valid_links);
-
- for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
- if (!(wpa_s->valid_links & BIT(i)))
- continue;
-
- wpa_printf(MSG_DEBUG, "MLD: link=%u, bssid=" MACSTR,
- i, MAC2STR(wpa_s->links[i].bssid));
- }
-
-out:
- wpabuf_free(mlbuf);
- return ret;
-}
-
-
static void wpas_ml_handle_removed_links(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss)
{
@@ -601,16 +388,98 @@
}
-static void wpas_sme_ml_auth(struct wpa_supplicant *wpa_s,
- union wpa_event_data *data,
- int ie_offset)
+#ifdef CONFIG_TESTING_OPTIONS
+static struct wpa_bss * wpas_ml_connect_pref(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss)
+{
+ unsigned int low, high, i;
+
+ wpa_printf(MSG_DEBUG,
+ "MLD: valid_links=%d, band_pref=%u, bssid_pref=" MACSTR,
+ wpa_s->valid_links,
+ wpa_s->conf->mld_connect_band_pref,
+ MAC2STR(wpa_s->conf->mld_connect_bssid_pref));
+
+ /* Check if there are more than one link */
+ if (!(wpa_s->valid_links & (wpa_s->valid_links - 1)))
+ return bss;
+
+ if (!is_zero_ether_addr(wpa_s->conf->mld_connect_bssid_pref)) {
+ for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+ if (!(wpa_s->valid_links & BIT(i)))
+ continue;
+
+ if (wpa_s->mlo_assoc_link_id == i)
+ continue;
+
+ if (ether_addr_equal(
+ wpa_s->links[i].bssid,
+ wpa_s->conf->mld_connect_bssid_pref))
+ goto found;
+ }
+ }
+
+ if (wpa_s->conf->mld_connect_band_pref == MLD_CONNECT_BAND_PREF_AUTO)
+ return bss;
+
+ switch (wpa_s->conf->mld_connect_band_pref) {
+ case MLD_CONNECT_BAND_PREF_2GHZ:
+ low = 2412;
+ high = 2472;
+ break;
+ case MLD_CONNECT_BAND_PREF_5GHZ:
+ low = 5180;
+ high = 5985;
+ break;
+ case MLD_CONNECT_BAND_PREF_6GHZ:
+ low = 5955;
+ high = 7125;
+ break;
+ default:
+ return bss;
+ }
+
+ for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+ if (!(wpa_s->valid_links & BIT(i)))
+ continue;
+
+ if (wpa_s->mlo_assoc_link_id == i)
+ continue;
+
+ if (wpa_s->links[i].freq >= low && wpa_s->links[i].freq <= high)
+ goto found;
+ }
+
+found:
+ if (i == MAX_NUM_MLD_LINKS) {
+ wpa_printf(MSG_DEBUG, "MLD: No match for connect/band pref");
+ return bss;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "MLD: Change BSS for connect: " MACSTR " -> " MACSTR,
+ MAC2STR(wpa_s->links[wpa_s->mlo_assoc_link_id].bssid),
+ MAC2STR(wpa_s->links[i].bssid));
+
+ /* Get the BSS entry and do the switch */
+ bss = wpa_bss_get_bssid(wpa_s, wpa_s->links[i].bssid);
+ wpa_s->mlo_assoc_link_id = i;
+
+ return bss;
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+
+static int wpas_sme_ml_auth(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data,
+ int ie_offset)
{
struct ieee802_11_elems elems;
const u8 *mld_addr;
u16 status_code = data->auth.status_code;
if (!wpa_s->valid_links)
- return;
+ return 0;
if (ieee802_11_parse_elems(data->auth.ies + ie_offset,
data->auth.ies_len - ie_offset,
@@ -628,7 +497,7 @@
goto out;
/* Accept missing Multi-Link element in failed authentication
* cases. */
- return;
+ return 0;
}
mld_addr = get_basic_mle_mld_addr(elems.basic_mle, elems.basic_mle_len);
@@ -637,16 +506,39 @@
wpa_printf(MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr));
- if (os_memcmp(wpa_s->ap_mld_addr, mld_addr, ETH_ALEN) != 0) {
+ if (!ether_addr_equal(wpa_s->ap_mld_addr, mld_addr)) {
wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected "
MACSTR ")", MAC2STR(wpa_s->ap_mld_addr));
goto out;
}
- return;
+ return 0;
out:
wpa_printf(MSG_DEBUG, "MLD: Authentication - clearing MLD state");
wpas_reset_mlo_info(wpa_s);
+ return -1;
+}
+
+
+static void wpas_sme_set_mlo_links(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss)
+{
+ int i;
+
+ wpa_s->valid_links = 0;
+
+ for (i = 0; i < bss->n_mld_links; i++) {
+ u8 link_id = bss->mld_links[i].link_id;
+ const u8 *bssid = bss->mld_links[i].bssid;
+
+ if (i == 0)
+ wpa_s->mlo_assoc_link_id = link_id;
+ wpa_s->valid_links |= BIT(link_id);
+ os_memcpy(wpa_s->links[link_id].bssid, bssid, ETH_ALEN);
+ wpa_s->links[link_id].freq = bss->mld_links[i].freq;
+ wpa_s->links[link_id].bss = wpa_bss_get_bssid(wpa_s, bssid);
+ wpa_s->links[link_id].disabled = bss->mld_links[i].disabled;
+ }
}
@@ -681,11 +573,33 @@
return;
}
+ os_memset(¶ms, 0, sizeof(params));
+
+ if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
+ !wpa_bss_parse_basic_ml_element(wpa_s, bss, wpa_s->ap_mld_addr,
+ NULL, ssid, NULL) &&
+ bss->n_mld_links) {
+ wpa_printf(MSG_DEBUG, "MLD: In authentication");
+ wpas_sme_set_mlo_links(wpa_s, bss);
+
+#ifdef CONFIG_TESTING_OPTIONS
+ bss = wpas_ml_connect_pref(wpa_s, bss);
+
+ if (wpa_s->conf->mld_force_single_link) {
+ wpa_printf(MSG_DEBUG, "MLD: Force single link");
+ wpa_s->valid_links = BIT(wpa_s->mlo_assoc_link_id);
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+ params.mld = true;
+ params.mld_link_id = wpa_s->mlo_assoc_link_id;
+ params.ap_mld_addr = wpa_s->ap_mld_addr;
+ wpas_ml_handle_removed_links(wpa_s, bss);
+ }
+
skip_auth = wpa_s->conf->reassoc_same_bss_optim &&
wpa_s->reassoc_same_bss;
wpa_s->current_bss = bss;
- os_memset(¶ms, 0, sizeof(params));
wpa_s->reassociate = 0;
params.freq = bss->freq;
@@ -694,14 +608,6 @@
params.ssid_len = bss->ssid_len;
params.p2p = ssid->p2p_group;
- if (wpas_ml_element(wpa_s, bss, ssid)) {
- wpa_printf(MSG_DEBUG, "MLD: In authentication");
- params.mld = true;
- params.mld_link_id = wpa_s->mlo_assoc_link_id;
- params.ap_mld_addr = wpa_s->ap_mld_addr;
- wpas_ml_handle_removed_links(wpa_s, bss);
- }
-
if (wpa_s->sme.ssid_len != params.ssid_len ||
os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0)
wpa_s->sme.prev_bssid_set = 0;
@@ -970,10 +876,12 @@
sme_auth_handle_rrm(wpa_s, bss);
+#ifndef CONFIG_NO_RRM
wpa_s->sme.assoc_req_ie_len += wpas_supp_op_class_ie(
wpa_s, ssid, bss,
wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len);
+#endif /* CONFIG_NO_RRM */
if (params.p2p)
wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
@@ -1122,7 +1030,7 @@
else
resp = sme_auth_build_sae_confirm(wpa_s, 0);
if (resp == NULL) {
- wpas_connection_failed(wpa_s, bss->bssid);
+ wpas_connection_failed(wpa_s, bss->bssid, NULL);
return;
}
params.auth_data = wpabuf_head(resp);
@@ -1258,7 +1166,7 @@
if (wpas_p2p_handle_frequency_conflicts(wpa_s,
params.freq,
ssid) < 0) {
- wpas_connection_failed(wpa_s, bss->bssid);
+ wpas_connection_failed(wpa_s, bss->bssid, NULL);
wpa_supplicant_mark_disassoc(wpa_s);
wpabuf_free(resp);
wpas_connect_work_done(wpa_s);
@@ -1281,7 +1189,7 @@
if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) {
wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the "
"driver failed");
- wpas_connection_failed(wpa_s, bss->bssid);
+ wpas_connection_failed(wpa_s, bss->bssid, NULL);
wpa_supplicant_mark_disassoc(wpa_s);
wpabuf_free(resp);
wpas_connect_work_done(wpa_s);
@@ -1719,8 +1627,7 @@
wpa_printf(MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr));
- if (os_memcmp(wpa_s->sme.ext_auth_ap_mld_addr, mld_addr, ETH_ALEN) !=
- 0) {
+ if (!ether_addr_equal(wpa_s->sme.ext_auth_ap_mld_addr, mld_addr)) {
wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected "
MACSTR ")",
MAC2STR(wpa_s->sme.ext_auth_ap_mld_addr));
@@ -1998,7 +1905,7 @@
}
if (wpa_insert_pmkid(wpa_s->sme.assoc_req_ie,
&wpa_s->sme.assoc_req_ie_len,
- wpa_s->sme.sae.pmkid) < 0)
+ wpa_s->sme.sae.pmkid, true) < 0)
return -1;
wpa_hexdump(MSG_DEBUG,
"SME: Updated Association Request IEs",
@@ -2075,9 +1982,9 @@
return;
}
- if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0 &&
+ if (!ether_addr_equal(wpa_s->pending_bssid, data->auth.peer) &&
!(wpa_s->valid_links &&
- os_memcmp(wpa_s->ap_mld_addr, data->auth.peer, ETH_ALEN) == 0)) {
+ ether_addr_equal(wpa_s->ap_mld_addr, data->auth.peer))) {
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with "
"unexpected peer " MACSTR,
MAC2STR(data->auth.peer));
@@ -2103,7 +2010,8 @@
data->auth.ies_len, 0, data->auth.peer,
&ie_offset);
if (res < 0) {
- wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
+ wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
+ NULL);
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
}
@@ -2147,7 +2055,8 @@
WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG ||
wpa_s->sme.auth_alg == data->auth.auth_type ||
wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) {
- wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
+ wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
+ NULL);
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
return;
}
@@ -2196,7 +2105,8 @@
" reason=%d locally_generated=1",
MAC2STR(wpa_s->pending_bssid),
WLAN_REASON_DEAUTH_LEAVING);
- wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
+ wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
+ NULL);
wpa_supplicant_mark_disassoc(wpa_s);
return;
}
@@ -2220,7 +2130,8 @@
" reason=%d locally_generated=1",
MAC2STR(wpa_s->pending_bssid),
WLAN_REASON_DEAUTH_LEAVING);
- wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
+ wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
+ NULL);
wpa_supplicant_mark_disassoc(wpa_s);
return;
}
@@ -2234,7 +2145,8 @@
" reason=%d locally_generated=1",
MAC2STR(wpa_s->pending_bssid),
WLAN_REASON_DEAUTH_LEAVING);
- wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
+ wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
+ NULL);
wpa_supplicant_mark_disassoc(wpa_s);
return;
}
@@ -2242,9 +2154,19 @@
#endif /* CONFIG_FILS */
/* TODO: Support additional auth_type values as well */
- if (data->auth.auth_type == WLAN_AUTH_OPEN ||
- data->auth.auth_type == WLAN_AUTH_SAE)
- wpas_sme_ml_auth(wpa_s, data, ie_offset);
+ if ((data->auth.auth_type == WLAN_AUTH_OPEN ||
+ data->auth.auth_type == WLAN_AUTH_SAE) &&
+ wpas_sme_ml_auth(wpa_s, data, ie_offset) < 0) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "MLD: Failed to parse ML Authentication frame");
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR
+ " reason=%d locally_generated=1",
+ MAC2STR(wpa_s->pending_bssid),
+ WLAN_REASON_DEAUTH_LEAVING);
+ wpas_connection_failed(wpa_s, wpa_s->pending_bssid, NULL);
+ wpa_supplicant_mark_disassoc(wpa_s);
+ return;
+ }
sme_associate(wpa_s, ssid->mode, data->auth.peer,
data->auth.auth_type);
@@ -2287,6 +2209,9 @@
os_memset(¶ms, 0, sizeof(params));
+ /* Save auth type, in case we need to retry after comeback timer. */
+ wpa_s->sme.assoc_auth_type = auth_type;
+
#ifdef CONFIG_FILS
if (auth_type == WLAN_AUTH_FILS_SK ||
auth_type == WLAN_AUTH_FILS_SK_PFS) {
@@ -2453,6 +2378,7 @@
pfs_fail:
#endif /* CONFIG_DPP2 */
+#ifndef CONFIG_NO_ROBUST_AV
wpa_s->mscs_setup_done = false;
if (wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS) &&
wpa_s->robust_av.valid_config) {
@@ -2486,6 +2412,7 @@
wpabuf_free(mscs_ie);
}
mscs_fail:
+#endif /* CONFIG_NO_ROBUST_AV */
if (ssid && ssid->multi_ap_backhaul_sta) {
size_t multi_ap_ie_len;
@@ -2682,19 +2609,48 @@
wpa_s->links[i].bssid;
params.mld_params.mld_links[i].freq =
wpa_s->links[i].freq;
+ params.mld_params.mld_links[i].disabled =
+ wpa_s->links[i].disabled;
- wpa_printf(MSG_DEBUG, "MLD: id=%u, freq=%d, " MACSTR,
+ wpa_printf(MSG_DEBUG,
+ "MLD: id=%u, freq=%d, disabled=%u, " MACSTR,
i, wpa_s->links[i].freq,
+ wpa_s->links[i].disabled,
MAC2STR(wpa_s->links[i].bssid));
}
}
if (wpa_drv_associate(wpa_s, ¶ms) < 0) {
+ unsigned int n_failed_links = 0;
+ int i;
+
wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the "
"driver failed");
- wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
- wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
- os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
+
+ /* Prepare list of failed links for error report */
+ for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+ if (!(wpa_s->valid_links & BIT(i)) ||
+ wpa_s->mlo_assoc_link_id == i ||
+ !params.mld_params.mld_links[i].error)
+ continue;
+
+ wpa_bssid_ignore_add(wpa_s, wpa_s->links[i].bssid);
+ n_failed_links++;
+ }
+
+ if (n_failed_links) {
+ /* Deauth and connect (possibly to the same AP MLD) */
+ wpa_drv_deauthenticate(wpa_s, wpa_s->ap_mld_addr,
+ WLAN_REASON_DEAUTH_LEAVING);
+ wpas_connect_work_done(wpa_s);
+ wpa_supplicant_mark_disassoc(wpa_s);
+ wpas_request_connection(wpa_s);
+ } else {
+ wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
+ NULL);
+ wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
+ os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
+ }
return;
}
@@ -2734,20 +2690,26 @@
}
-static void sme_deauth(struct wpa_supplicant *wpa_s)
+static void sme_deauth(struct wpa_supplicant *wpa_s, const u8 **link_bssids)
{
int bssid_changed;
+ const u8 *bssid;
bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
- if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
+ if (wpa_s->valid_links)
+ bssid = wpa_s->ap_mld_addr;
+ else
+ bssid = wpa_s->pending_bssid;
+
+ if (wpa_drv_deauthenticate(wpa_s, bssid,
WLAN_REASON_DEAUTH_LEAVING) < 0) {
wpa_msg(wpa_s, MSG_INFO, "SME: Deauth request to the driver "
"failed");
}
wpa_s->sme.prev_bssid_set = 0;
- wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
+ wpas_connection_failed(wpa_s, wpa_s->pending_bssid, link_bssids);
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
os_memset(wpa_s->bssid, 0, ETH_ALEN);
os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
@@ -2756,14 +2718,115 @@
}
-void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
- union wpa_event_data *data)
+static void sme_assoc_comeback_timer(void *eloop_ctx, void *timeout_ctx)
{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+
+ if (!wpa_s->current_bss || !wpa_s->current_ssid) {
+ wpa_msg(wpa_s, MSG_DEBUG,
+ "SME: Comeback timeout expired; SSID/BSSID cleared; ignoring");
+ return;
+ }
+
+ wpa_msg(wpa_s, MSG_DEBUG,
+ "SME: Comeback timeout expired; retry associating with "
+ MACSTR "; mode=%d auth_type=%u",
+ MAC2STR(wpa_s->current_bss->bssid),
+ wpa_s->current_ssid->mode,
+ wpa_s->sme.assoc_auth_type);
+
+ /* Authentication state was completed already; just try association
+ * again. */
+ sme_associate(wpa_s, wpa_s->current_ssid->mode,
+ wpa_s->current_bss->bssid,
+ wpa_s->sme.assoc_auth_type);
+}
+
+
+static bool sme_try_assoc_comeback(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+ struct ieee802_11_elems elems;
+ u32 timeout_interval;
+ unsigned long comeback_usec;
+ u8 type = WLAN_TIMEOUT_ASSOC_COMEBACK;
+
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->test_assoc_comeback_type != -1)
+ type = wpa_s->test_assoc_comeback_type;
+#endif /* CONFIG_TESTING_OPTIONS */
+
+ if (ieee802_11_parse_elems(data->assoc_reject.resp_ies,
+ data->assoc_reject.resp_ies_len,
+ &elems, 0) == ParseFailed) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "SME: Temporary assoc reject: failed to parse (Re)Association Response frame elements");
+ return false;
+ }
+
+ if (!elems.timeout_int) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "SME: Temporary assoc reject: missing timeout interval IE");
+ return false;
+ }
+
+ if (elems.timeout_int[0] != type) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "SME: Temporary assoc reject: missing association comeback time");
+ return false;
+ }
+
+ timeout_interval = WPA_GET_LE32(&elems.timeout_int[1]);
+ if (timeout_interval > 60000) {
+ /* This is unprotected information and there is no point in
+ * getting stuck waiting for very long duration based on it */
+ wpa_msg(wpa_s, MSG_DEBUG,
+ "SME: Ignore overly long association comeback interval: %u TUs",
+ timeout_interval);
+ return false;
+ }
+ wpa_msg(wpa_s, MSG_DEBUG, "SME: Association comeback interval: %u TUs",
+ timeout_interval);
+
+ comeback_usec = timeout_interval * 1024;
+ eloop_register_timeout(comeback_usec / 1000000, comeback_usec % 1000000,
+ sme_assoc_comeback_timer, wpa_s, NULL);
+ return true;
+}
+
+
+void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data,
+ const u8 **link_bssids)
+{
+ const u8 *bssid;
+
+ if (wpa_s->valid_links)
+ bssid = wpa_s->ap_mld_addr;
+ else
+ bssid = wpa_s->pending_bssid;
+
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association with " MACSTR " failed: "
"status code %d", MAC2STR(wpa_s->pending_bssid),
data->assoc_reject.status_code);
eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
+ eloop_cancel_timeout(sme_assoc_comeback_timer, wpa_s, NULL);
+
+ /* Authentication phase has been completed at this point. Check whether
+ * the AP rejected association temporarily due to still holding a
+ * security associationis with us (MFP). If so, we must wait for the
+ * AP's association comeback timeout period before associating again. */
+ if (data->assoc_reject.status_code ==
+ WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
+ wpa_msg(wpa_s, MSG_DEBUG,
+ "SME: Temporary association reject from BSS " MACSTR,
+ MAC2STR(bssid));
+ if (sme_try_assoc_comeback(wpa_s, data)) {
+ /* Break out early; comeback error is not a failure. */
+ return;
+ }
+ }
#ifdef CONFIG_SAE
if (wpa_s->sme.sae_pmksa_caching && wpa_s->current_ssid &&
@@ -2776,7 +2839,7 @@
struct wpa_bss *bss = wpa_s->current_bss;
struct wpa_ssid *ssid = wpa_s->current_ssid;
- wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
+ wpa_drv_deauthenticate(wpa_s, bssid,
WLAN_REASON_DEAUTH_LEAVING);
wpas_connect_work_done(wpa_s);
wpa_supplicant_mark_disassoc(wpa_s);
@@ -2821,7 +2884,7 @@
* benefit from using the previous authentication, so this could be
* optimized in the future.
*/
- sme_deauth(wpa_s);
+ sme_deauth(wpa_s, link_bssids);
}
@@ -2829,7 +2892,7 @@
union wpa_event_data *data)
{
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication timed out");
- wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
+ wpas_connection_failed(wpa_s, wpa_s->pending_bssid, NULL);
wpa_supplicant_mark_disassoc(wpa_s);
}
@@ -2838,7 +2901,7 @@
union wpa_event_data *data)
{
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association timed out");
- wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
+ wpas_connection_failed(wpa_s, wpa_s->pending_bssid, NULL);
wpa_supplicant_mark_disassoc(wpa_s);
}
@@ -2867,7 +2930,7 @@
struct wpa_supplicant *wpa_s = eloop_ctx;
if (wpa_s->wpa_state == WPA_AUTHENTICATING) {
wpa_msg(wpa_s, MSG_DEBUG, "SME: Authentication timeout");
- sme_deauth(wpa_s);
+ sme_deauth(wpa_s, NULL);
}
}
@@ -2877,7 +2940,7 @@
struct wpa_supplicant *wpa_s = eloop_ctx;
if (wpa_s->wpa_state == WPA_ASSOCIATING) {
wpa_msg(wpa_s, MSG_DEBUG, "SME: Association timeout");
- sme_deauth(wpa_s);
+ sme_deauth(wpa_s, NULL);
}
}
@@ -2885,35 +2948,15 @@
void sme_state_changed(struct wpa_supplicant *wpa_s)
{
/* Make sure timers are cleaned up appropriately. */
- if (wpa_s->wpa_state != WPA_ASSOCIATING)
+ if (wpa_s->wpa_state != WPA_ASSOCIATING) {
eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
+ eloop_cancel_timeout(sme_assoc_comeback_timer, wpa_s, NULL);
+ }
if (wpa_s->wpa_state != WPA_AUTHENTICATING)
eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
}
-void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s,
- const u8 *prev_pending_bssid)
-{
- /*
- * mac80211-workaround to force deauth on failed auth cmd,
- * requires us to remain in authenticating state to allow the
- * second authentication attempt to be continued properly.
- */
- wpa_dbg(wpa_s, MSG_DEBUG, "SME: Allow pending authentication "
- "to proceed after disconnection event");
- wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
- os_memcpy(wpa_s->pending_bssid, prev_pending_bssid, ETH_ALEN);
-
- /*
- * Re-arm authentication timer in case auth fails for whatever reason.
- */
- eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
- eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
- NULL);
-}
-
-
void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s)
{
wpa_s->sme.prev_bssid_set = 0;
@@ -2941,6 +2984,7 @@
eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
+ eloop_cancel_timeout(sme_assoc_comeback_timer, wpa_s, NULL);
}
@@ -3374,7 +3418,7 @@
ssid = wpa_s->current_ssid;
if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION)
return;
- if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
+ if (!ether_addr_equal(sa, wpa_s->bssid))
return;
if (reason_code != WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA &&
reason_code != WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA)
@@ -3479,7 +3523,7 @@
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from "
MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
- if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
+ if (!ether_addr_equal(sa, wpa_s->bssid))
return;
for (i = 0; i < wpa_s->sme.sa_query_count; i++) {
diff --git a/wpa_supplicant/sme.h b/wpa_supplicant/sme.h
index c797d2e..f8fd06b 100644
--- a/wpa_supplicant/sme.h
+++ b/wpa_supplicant/sme.h
@@ -19,7 +19,8 @@
int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
const u8 *ies, size_t ies_len);
void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
- union wpa_event_data *data);
+ union wpa_event_data *data,
+ const u8 **link_bssids);
void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s,
union wpa_event_data *data);
void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
@@ -32,8 +33,6 @@
void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *da, const u8 *sa,
const u8 *data, size_t len);
void sme_state_changed(struct wpa_supplicant *wpa_s);
-void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s,
- const u8 *prev_pending_bssid);
void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s);
void sme_deinit(struct wpa_supplicant *wpa_s);
@@ -65,7 +64,8 @@
static inline void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
- union wpa_event_data *data)
+ union wpa_event_data *data,
+ const u8 **link_bssids)
{
}
@@ -98,12 +98,6 @@
{
}
-static inline void
-sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s,
- const u8 *prev_pending_bssid)
-{
-}
-
static inline void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s)
{
}
diff --git a/wpa_supplicant/wmm_ac.c b/wpa_supplicant/wmm_ac.c
index d0fdd55..37e2ed4 100644
--- a/wpa_supplicant/wmm_ac.c
+++ b/wpa_supplicant/wmm_ac.c
@@ -678,7 +678,7 @@
}
/* make sure the params are the same */
- if (os_memcmp(req->address, sa, ETH_ALEN) != 0 ||
+ if (!ether_addr_equal(req->address, sa) ||
tsid != wmm_ac_get_tsid(&req->tspec) ||
up != wmm_ac_get_user_priority(&req->tspec) ||
dir != wmm_ac_get_direction(&req->tspec)) {
@@ -755,13 +755,13 @@
}
/* WMM AC action frame */
- if (os_memcmp(da, wpa_s->own_addr, ETH_ALEN) != 0) {
+ if (!ether_addr_equal(da, wpa_s->own_addr)) {
wpa_printf(MSG_DEBUG, "WMM AC: frame destination addr="MACSTR
" is other than ours, ignoring frame", MAC2STR(da));
return;
}
- if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) {
+ if (!ether_addr_equal(sa, wpa_s->bssid)) {
wpa_printf(MSG_DEBUG, "WMM AC: ignore frame with sa " MACSTR
" different other than our bssid", MAC2STR(da));
return;
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index 56183ff..775e75b 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -686,9 +686,8 @@
if (reason) {
for (i = 0; i < info->num; i++) {
if (first_candidate_bssid &&
- os_memcmp(first_candidate_bssid,
- info->candidates[i].bssid, ETH_ALEN) == 0)
- {
+ ether_addr_equal(first_candidate_bssid,
+ info->candidates[i].bssid)) {
*reason = info->candidates[i].reject_reason;
break;
}
@@ -1091,7 +1090,7 @@
wpabuf_put_data(buf, "\0\0\0\0\0\0", ETH_ALEN);
}
- if (status == WNM_BSS_TM_ACCEPT)
+ if (status == WNM_BSS_TM_ACCEPT && !wpa_s->wnm_link_removal)
wnm_add_cand_list(wpa_s, &buf);
#ifdef CONFIG_MBO
@@ -1194,8 +1193,8 @@
}
if (!wpa_s->current_bss ||
- os_memcmp(wpa_s->wnm_cand_from_bss, wpa_s->current_bss->bssid,
- ETH_ALEN) != 0) {
+ !ether_addr_equal(wpa_s->wnm_cand_from_bss,
+ wpa_s->current_bss->bssid)) {
wpa_printf(MSG_DEBUG, "WNM: Stored BSS transition candidate list not from the current BSS - ignore it");
return 0;
}
@@ -1388,7 +1387,7 @@
const u8 *ssid_ie;
res = scan_res->res[j];
- if (os_memcmp(nei->bssid, res->bssid, ETH_ALEN) != 0 ||
+ if (!ether_addr_equal(nei->bssid, res->bssid) ||
res->age > WNM_SCAN_RESULT_AGE * 1000)
continue;
bss = wpa_s->current_bss;
@@ -1437,6 +1436,7 @@
#ifdef CONFIG_MBO
const u8 *vendor;
#endif /* CONFIG_MBO */
+ bool disassoc_imminent;
if (wpa_s->disable_mbo_oce || wpa_s->conf->disable_btm)
return;
@@ -1461,6 +1461,7 @@
wpa_s->wnm_dialog_token = pos[0];
wpa_s->wnm_mode = pos[1];
wpa_s->wnm_dissoc_timer = WPA_GET_LE16(pos + 2);
+ wpa_s->wnm_link_removal = false;
valid_int = pos[4];
wpa_s->wnm_reply = reply;
@@ -1532,7 +1533,26 @@
return;
}
- if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
+ disassoc_imminent = wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
+
+ /*
+ * Based on IEEE P802.11be/D5.0, when a station is a non-AP MLD with
+ * more than one affiliated link, the Link Removal Imminent field is
+ * set to 1, and the BSS Termination Included field is set to 1, only
+ * one of the links is removed and the other links remain associated.
+ * Ignore the Disassociation Imminent field in such a case.
+ */
+ if (disassoc_imminent &&
+ (wpa_s->valid_links & (wpa_s->valid_links - 1)) != 0 &&
+ (wpa_s->wnm_mode & WNM_BSS_TM_REQ_LINK_REMOVAL_IMMINENT) &&
+ (wpa_s->wnm_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED)) {
+ wpa_printf(MSG_INFO,
+ "WNM: BTM request for a single MLO link - ignore disassociation imminent since other links remain associated");
+ disassoc_imminent = false;
+ wpa_s->wnm_link_removal = true;
+ }
+
+ if (disassoc_imminent) {
wpa_msg(wpa_s, MSG_INFO, "WNM: Disassociation Imminent - "
"Disassociation Timer %u", wpa_s->wnm_dissoc_timer);
if (wpa_s->wnm_dissoc_timer && !wpa_s->scanning &&
@@ -1572,8 +1592,7 @@
wnm_parse_neighbor_report(wpa_s, pos, len, rep);
if ((wpa_s->wnm_mode &
WNM_BSS_TM_REQ_DISASSOC_IMMINENT) &&
- os_memcmp(rep->bssid, wpa_s->bssid,
- ETH_ALEN) == 0)
+ ether_addr_equal(rep->bssid, wpa_s->bssid))
rep->disassoc_imminent = 1;
wpa_s->wnm_num_neighbor_report++;
@@ -1666,7 +1685,9 @@
wpa_supplicant_req_scan(wpa_s, 0, 0);
} else if (reply) {
enum bss_trans_mgmt_status_code status;
- if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT)
+
+ if ((wpa_s->wnm_mode & WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT) ||
+ wpa_s->wnm_link_removal)
status = WNM_BSS_TM_ACCEPT;
else {
wpa_msg(wpa_s, MSG_INFO, "WNM: BSS Transition Management Request did not include candidates");
@@ -1890,7 +1911,9 @@
pos, end - pos);
if (wpa_s->wpa_state != WPA_COMPLETED ||
- os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) {
+ (!ether_addr_equal(sa, wpa_s->bssid) &&
+ (!wpa_s->valid_links ||
+ !ether_addr_equal(sa, wpa_s->ap_mld_addr)))) {
wpa_dbg(wpa_s, MSG_DEBUG, "WNM: WNM-Notification frame not "
"from our AP - ignore it");
return;
@@ -1934,7 +1957,9 @@
return; /* only nonzero values are used for request */
if (wpa_s->wpa_state != WPA_COMPLETED ||
- os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) {
+ (!ether_addr_equal(sa, wpa_s->bssid) &&
+ (!wpa_s->valid_links ||
+ !ether_addr_equal(sa, wpa_s->ap_mld_addr)))) {
wpa_dbg(wpa_s, MSG_DEBUG,
"WNM: Collocated Interference Request frame not from current AP - ignore it");
return;
@@ -1964,7 +1989,9 @@
wpa_printf(MSG_DEBUG, "WNM: RX action %u from " MACSTR,
act, MAC2STR(mgmt->sa));
if (wpa_s->wpa_state < WPA_ASSOCIATED ||
- os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) != 0) {
+ (!ether_addr_equal(mgmt->sa, wpa_s->bssid) &&
+ (!wpa_s->valid_links ||
+ !ether_addr_equal(mgmt->sa, wpa_s->ap_mld_addr)))) {
wpa_printf(MSG_DEBUG, "WNM: Ignore unexpected WNM Action "
"frame");
return;
@@ -2048,8 +2075,43 @@
void wnm_clear_coloc_intf_reporting(struct wpa_supplicant *wpa_s)
{
-#ifdef CONFIG_WNM
wpa_s->coloc_intf_dialog_token = 0;
wpa_s->coloc_intf_auto_report = 0;
-#endif /* CONFIG_WNM */
+}
+
+
+bool wnm_is_bss_excluded(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
+{
+ unsigned int i;
+
+ if (!(wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))
+ return false;
+
+ /*
+ * In case disassociation imminent is set, do no try to use a BSS to
+ * which we are connected.
+ */
+
+ if (wpa_s->current_bss &&
+ ether_addr_equal(wpa_s->current_bss->bssid, bss->bssid)) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WNM: Disassociation imminent: current BSS");
+ return true;
+ }
+
+ if (!wpa_s->valid_links)
+ return false;
+
+ for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+ if (!(wpa_s->valid_links & BIT(i)))
+ continue;
+
+ if (ether_addr_equal(wpa_s->links[i].bssid, bss->bssid)) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WNM: MLD: Disassociation imminent: current link");
+ return true;
+ }
+ }
+
+ return false;
}
diff --git a/wpa_supplicant/wnm_sta.h b/wpa_supplicant/wnm_sta.h
index e4957e4..2a473db 100644
--- a/wpa_supplicant/wnm_sta.h
+++ b/wpa_supplicant/wnm_sta.h
@@ -70,6 +70,7 @@
const struct wpabuf *elems);
void wnm_set_coloc_intf_elems(struct wpa_supplicant *wpa_s,
struct wpabuf *elems);
+bool wnm_is_bss_excluded(struct wpa_supplicant *wpa_s, struct wpa_bss *bss);
#ifdef CONFIG_WNM
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 65078ed..b1334e2 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -2847,6 +2847,8 @@
}
+#ifndef CONFIG_NO_WMM_AC
+
static int wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -2867,6 +2869,8 @@
return wpa_ctrl_command(ctrl, "WMM_AC_STATUS");
}
+#endif /* CONFIG_NO_WMM_AC */
+
static int wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl *ctrl, int argc,
char *argv[])
@@ -3889,6 +3893,7 @@
{ "tdls_link_status", wpa_cli_cmd_tdls_link_status, NULL,
cli_cmd_flag_none,
"<addr> = TDLS link status with <addr>" },
+#ifndef CONFIG_NO_WMM_AC
{ "wmm_ac_addts", wpa_cli_cmd_wmm_ac_addts, NULL,
cli_cmd_flag_none,
"<uplink/downlink/bidi> <tsid=0..7> <up=0..7> [nominal_msdu_size=#] "
@@ -3900,6 +3905,7 @@
{ "wmm_ac_status", wpa_cli_cmd_wmm_ac_status, NULL,
cli_cmd_flag_none,
"= show status for Wireless Multi-Media Admission-Control" },
+#endif /* CONFIG_NO_WMM_AC */
{ "tdls_chan_switch", wpa_cli_cmd_tdls_chan_switch, NULL,
cli_cmd_flag_none,
"<addr> <oper class> <freq> [sec_channel_offset=] [center_freq1=] "
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index d4401ff..a851024 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant
- * Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2024, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -65,6 +65,7 @@
#include "wpas_kay.h"
#include "mesh.h"
#include "dpp_supplicant.h"
+#include "nan_usd.h"
#ifdef CONFIG_MESH
#include "ap/ap_config.h"
#include "ap/hostapd.h"
@@ -584,7 +585,9 @@
wpa_tdls_deinit(wpa_s->wpa);
#endif /* CONFIG_TDLS */
+#ifndef CONFIG_NO_WMM_AC
wmm_ac_clear_saved_tspecs(wpa_s);
+#endif /* CONFIG_NO_WMM_AC */
pmksa_candidate_free(wpa_s->wpa);
ptksa_cache_deinit(wpa_s->ptksa);
wpa_s->ptksa = NULL;
@@ -701,7 +704,9 @@
wpa_s->vendor_elem[i] = NULL;
}
+#ifndef CONFIG_NO_WMM_AC
wmm_ac_notify_disassoc(wpa_s);
+#endif /* CONFIG_NO_WMM_AC */
wpa_s->sched_scan_plans_num = 0;
os_free(wpa_s->sched_scan_plans);
@@ -717,7 +722,9 @@
wpabuf_free(wpa_s->lci);
wpa_s->lci = NULL;
+#ifndef CONFIG_NO_RRM
wpas_clear_beacon_rep_data(wpa_s);
+#endif /* CONFIG_NO_RRM */
#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
#ifdef CONFIG_MESH
@@ -746,11 +753,17 @@
wpa_s->dpp = NULL;
#endif /* CONFIG_DPP */
+#ifdef CONFIG_NAN_USD
+ wpas_nan_usd_deinit(wpa_s);
+#endif /* CONFIG_NAN_USD */
+
#ifdef CONFIG_PASN
wpas_pasn_auth_stop(wpa_s);
#endif /* CONFIG_PASN */
+#ifndef CONFIG_NO_ROBUST_AV
wpas_scs_deinit(wpa_s);
wpas_dscp_deinit(wpa_s);
+#endif /* CONFIG_NO_ROBUST_AV */
#ifdef CONFIG_OWE
os_free(wpa_s->owe_trans_scan_freq);
@@ -1068,8 +1081,10 @@
if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
wpa_supplicant_start_autoscan(wpa_s);
+#ifndef CONFIG_NO_WMM_AC
if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
wmm_ac_notify_disassoc(wpa_s);
+#endif /* CONFIG_NO_WMM_AC */
if (wpa_s->wpa_state != old_state) {
wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
@@ -2009,7 +2024,7 @@
(wpa_s->connection_ht || wpa_s->connection_vht ||
wpa_s->connection_he || wpa_s->connection_eht);
if (!wmm && bss)
- wmm = wpa_bss_get_vendor_ie(bss, WMM_IE_VENDOR_TYPE);
+ wmm = !!wpa_bss_get_vendor_ie(bss, WMM_IE_VENDOR_TYPE);
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_WMM_ENABLED, wmm);
if (!skip_default_rsne) {
@@ -2111,7 +2126,9 @@
static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx,
struct wpa_bss *bss)
{
+#ifndef CONFIG_NO_ROBUST_AV
bool scs = true, mscs = true;
+#endif /* CONFIG_NO_ROBUST_AV */
*pos = 0x00;
@@ -2127,7 +2144,9 @@
case 2: /* Bits 16-23 */
#ifdef CONFIG_WNM
*pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
- if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
+ if ((wpas_driver_bss_selection(wpa_s) ||
+ !wpa_s->disable_mbo_oce) &&
+ !wpa_s->conf->disable_btm)
*pos |= 0x08; /* Bit 19 - BSS Transition */
#endif /* CONFIG_WNM */
break;
@@ -2156,6 +2175,7 @@
#endif /* CONFIG_MBO */
break;
case 6: /* Bits 48-55 */
+#ifndef CONFIG_NO_ROBUST_AV
#ifdef CONFIG_TESTING_OPTIONS
if (wpa_s->disable_scs_support)
scs = false;
@@ -2169,6 +2189,7 @@
}
if (scs)
*pos |= 0x40; /* Bit 54 - SCS */
+#endif /* CONFIG_NO_ROBUST_AV */
break;
case 7: /* Bits 56-63 */
break;
@@ -2185,6 +2206,7 @@
#endif /* CONFIG_FILS */
break;
case 10: /* Bits 80-87 */
+#ifndef CONFIG_NO_ROBUST_AV
#ifdef CONFIG_TESTING_OPTIONS
if (wpa_s->disable_mscs_support)
mscs = false;
@@ -2198,6 +2220,7 @@
}
if (mscs)
*pos |= 0x20; /* Bit 85 - Mirrored SCS */
+#endif /* CONFIG_NO_ROBUST_AV */
break;
}
}
@@ -2315,8 +2338,7 @@
if (style == WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS) {
/* Pregenerated addresses do not expire but their value
* might have changed, so let's check that. */
- if (os_memcmp(wpa_s->own_addr, ssid->mac_value,
- ETH_ALEN) == 0)
+ if (ether_addr_equal(wpa_s->own_addr, ssid->mac_value))
return 0;
} else if ((wpa_s->last_mac_addr_change.sec != 0 ||
wpa_s->last_mac_addr_change.usec != 0) &&
@@ -2495,7 +2517,12 @@
wpa_s->eapol_failed = 0;
wpa_s->multi_ap_ie = 0;
+#ifndef CONFIG_NO_WMM_AC
wmm_ac_clear_saved_tspecs(wpa_s);
+#endif /* CONFIG_NO_WMM_AC */
+#ifdef CONFIG_WNM
+ wpa_s->wnm_mode = 0;
+#endif /* CONFIG_WNM */
wpa_s->reassoc_same_bss = 0;
wpa_s->reassoc_same_ess = 0;
#ifdef CONFIG_TESTING_OPTIONS
@@ -2506,7 +2533,9 @@
wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
wpa_s->reassoc_same_ess = 1;
if (wpa_s->current_bss && wpa_s->current_bss == bss) {
+#ifndef CONFIG_NO_WMM_AC
wmm_ac_save_tspecs(wpa_s);
+#endif /* CONFIG_NO_WMM_AC */
wpa_s->reassoc_same_bss = 1;
} else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
os_get_reltime(&wpa_s->roam_start);
@@ -3074,7 +3103,7 @@
struct hostapd_hw_modes *mode = NULL;
int i, obss_scan = 1;
u8 channel;
- bool is_6ghz;
+ bool is_6ghz, is_24ghz;
freq->freq = ssid->frequency;
@@ -3103,6 +3132,9 @@
if (!mode)
return;
+ is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
+ hw_mode == HOSTAPD_MODE_IEEE80211B;
+
is_6ghz = is_6ghz_freq(freq->freq);
freq->ht_enabled = 0;
@@ -3114,7 +3146,7 @@
freq->ht_enabled = ibss_mesh_can_use_ht(wpa_s, ssid, mode);
if (freq->ht_enabled)
freq->vht_enabled = ibss_mesh_can_use_vht(wpa_s, ssid, mode);
- if (freq->vht_enabled || is_6ghz)
+ if (freq->vht_enabled || (freq->ht_enabled && is_24ghz) || is_6ghz)
freq->he_enabled = ibss_mesh_can_use_he(wpa_s, ssid, mode,
ieee80211_mode);
freq->channel = channel;
@@ -3256,8 +3288,10 @@
size_t wfa_ie_len, buf_len;
os_memset(wfa_capa, 0, sizeof(wfa_capa));
+#ifndef CONFIG_NO_ROBUST_AV
if (wpa_s->enable_dscp_policy_capa)
wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
+#endif /* CONFIG_NO_ROBUST_AV */
if (wpa_is_non_eht_scs_traffic_desc_supported(bss))
wfa_capa[0] |= WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC;
@@ -3521,12 +3555,14 @@
os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
#endif /* CONFIG_P2P */
+#ifndef CONFIG_NO_RRM
if (bss) {
wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
wpa_ie + wpa_ie_len,
max_wpa_ie_len -
wpa_ie_len);
}
+#endif /* CONFIG_NO_RRM */
/*
* Workaround: Add Extended Capabilities element only if the AP
@@ -3753,6 +3789,7 @@
wpa_ie_len += wpa_s->rsnxe_len;
}
+#ifndef CONFIG_NO_ROBUST_AV
#ifdef CONFIG_TESTING_OPTIONS
if (wpa_s->disable_mscs_support)
goto mscs_end;
@@ -3787,6 +3824,7 @@
wpabuf_free(mscs_ie);
}
mscs_end:
+#endif /* CONFIG_NO_ROBUST_AV */
wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
max_wpa_ie_len);
@@ -4071,7 +4109,9 @@
wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
wpa_s->rsnxe_len = 0;
+#ifndef CONFIG_NO_ROBUST_AV
wpa_s->mscs_setup_done = false;
+#endif /* CONFIG_NO_ROBUST_AV */
wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, ¶ms, NULL);
if (!wpa_ie) {
@@ -4466,7 +4506,8 @@
* can stop right here; the association will not
* succeed.
*/
- wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
+ wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
+ NULL);
wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
@@ -4562,8 +4603,10 @@
if (old_ssid != wpa_s->current_ssid)
wpas_notify_network_changed(wpa_s);
+#ifndef CONFIG_NO_ROBUST_AV
wpas_scs_deinit(wpa_s);
wpas_dscp_deinit(wpa_s);
+#endif /* CONFIG_NO_ROBUST_AV */
eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
}
@@ -5343,14 +5386,14 @@
os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
wired) &&
(!entry->bssid_set ||
- os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
+ ether_addr_equal(bssid, entry->bssid)))
return entry;
#ifdef CONFIG_WPS
if (!wpas_network_disabled(wpa_s, entry) &&
(entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
(entry->ssid == NULL || entry->ssid_len == 0) &&
(!entry->bssid_set ||
- os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
+ ether_addr_equal(bssid, entry->bssid)))
return entry;
#endif /* CONFIG_WPS */
@@ -5360,13 +5403,13 @@
owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
entry->ssid_len)) &&
(!entry->bssid_set ||
- os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
+ ether_addr_equal(bssid, entry->bssid)))
return entry;
#endif /* CONFIG_OWE */
if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
entry->ssid_len == 0 &&
- os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
+ ether_addr_equal(bssid, entry->bssid))
return entry;
entry = entry->next;
@@ -5494,7 +5537,7 @@
#ifdef CONFIG_AP
!wpa_s->ap_iface &&
#endif /* CONFIG_AP */
- os_memcmp(src_addr, connected_addr, ETH_ALEN) != 0)) {
+ !ether_addr_equal(src_addr, connected_addr))) {
/*
* There is possible race condition between receiving the
* association event and the EAPOL frame since they are coming
@@ -5524,7 +5567,7 @@
}
wpa_s->last_eapol_matches_bssid =
- os_memcmp(src_addr, connected_addr, ETH_ALEN) == 0;
+ ether_addr_equal(src_addr, connected_addr);
#ifdef CONFIG_AP
if (wpa_s->ap_iface) {
@@ -5681,7 +5724,7 @@
fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
#endif /* CONFIG_FST */
- if (os_memcmp(prev_mac_addr, wpa_s->own_addr, ETH_ALEN) != 0)
+ if (!ether_addr_equal(prev_mac_addr, wpa_s->own_addr))
wpas_notify_mac_address_changed(wpa_s);
return 0;
@@ -5698,7 +5741,7 @@
return;
eth = (const struct l2_ethhdr *) buf;
- if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
+ if (!ether_addr_equal(eth->h_dest, wpa_s->own_addr) &&
!(eth->h_dest[0] & 0x01)) {
wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
" (bridge - not for this interface - ignore)",
@@ -5873,8 +5916,11 @@
dl_list_init(&wpa_s->fils_hlp_req);
#ifdef CONFIG_TESTING_OPTIONS
dl_list_init(&wpa_s->drv_signal_override);
+ wpa_s->test_assoc_comeback_type = -1;
#endif /* CONFIG_TESTING_OPTIONS */
+#ifndef CONFIG_NO_ROBUST_AV
dl_list_init(&wpa_s->active_scs_ids);
+#endif /* CONFIG_NO_ROBUST_AV */
wpa_s->ml_probe_mld_id = -1;
return wpa_s;
@@ -6387,7 +6433,7 @@
{
struct wpa_supplicant *wpa_s = ctx;
- if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
+ if (!ether_addr_equal(wpa_s->bssid, da)) {
wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
__func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
return -1;
@@ -6403,7 +6449,7 @@
{
struct wpa_supplicant *wpa_s = ctx;
- WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
+ WPA_ASSERT(ether_addr_equal(wpa_s->bssid, addr));
return wpa_s->received_mb_ies;
}
@@ -6414,7 +6460,7 @@
struct wpa_supplicant *wpa_s = ctx;
struct mb_ies_info info;
- WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
+ WPA_ASSERT(ether_addr_equal(wpa_s->bssid, addr));
if (!mb_ies_info_by_ies(&info, buf, size)) {
wpabuf_free(wpa_s->received_mb_ies);
@@ -7203,6 +7249,9 @@
return -1;
}
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_PREPEND_PMKID,
+ wpa_s->conf->ft_prepend_pmkid);
+
wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
&wpa_s->hw.num_modes,
&wpa_s->hw.flags,
@@ -7251,7 +7300,9 @@
wpa_s->extended_capa_len = capa.extended_capa_len;
wpa_s->num_multichan_concurrent =
capa.num_multichan_concurrent;
+#ifndef CONFIG_NO_WMM_AC
wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
+#endif /* CONFIG_NO_WMM_AC */
wpa_s->max_num_akms = capa.max_num_akms;
if (capa.mac_addr_rand_scan_supported)
@@ -7339,6 +7390,11 @@
return -1;
#endif /* CONFIG_DPP */
+#ifdef CONFIG_NAN_USD
+ if (wpas_nan_usd_init(wpa_s) < 0)
+ return -1;
+#endif /* CONFIG_NAN_USD */
+
if (wpa_supplicant_init_eapol(wpa_s) < 0)
return -1;
wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
@@ -7408,7 +7464,9 @@
if (wpas_init_ext_pw(wpa_s) < 0)
return -1;
+#ifndef CONFIG_NO_RRM
wpas_rrm_reset(wpa_s);
+#endif /* CONFIG_NO_RRM */
wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
@@ -8173,6 +8231,10 @@
if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
wpa_supplicant_set_default_scan_ies(wpa_s);
+ if (wpa_s->conf->changed_parameters & CFG_CHANGED_FT_PREPEND_PMKID)
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_PREPEND_PMKID,
+ wpa_s->conf->ft_prepend_pmkid);
+
#ifdef CONFIG_BGSCAN
/*
* We default to global bgscan parameters only when per-network bgscan
@@ -8241,7 +8303,8 @@
}
-void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
+void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const u8 **link_bssids)
{
int timeout;
int count;
@@ -8276,6 +8339,12 @@
return;
}
+ /* Also mark links as failed */
+ while (link_bssids && *link_bssids) {
+ wpa_bssid_ignore_add(wpa_s, *link_bssids);
+ link_bssids++;
+ }
+
/*
* Add the failed BSSID into the ignore list and speed up next scan
* attempt if there could be other APs that could accept association.
@@ -8692,9 +8761,16 @@
int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
{
if (wpa_s->current_ssid == NULL ||
- wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
- os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
+ wpa_s->wpa_state < WPA_4WAY_HANDSHAKE)
return 0;
+ if (wpa_s->valid_links) {
+ if (!ether_addr_equal(addr, wpa_s->ap_mld_addr) &&
+ !wpas_ap_link_address(wpa_s, addr))
+ return 0;
+ } else {
+ if (!ether_addr_equal(addr, wpa_s->bssid))
+ return 0;
+ }
return wpa_sm_pmf_enabled(wpa_s->wpa);
}
@@ -8819,8 +8895,8 @@
return 0;
for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
- if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
- bssid, ETH_ALEN) == 0)
+ if (ether_addr_equal(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
+ bssid))
return 1;
}
@@ -9130,7 +9206,7 @@
dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
struct wpa_bss_tmp_disallowed, list) {
- if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
+ if (ether_addr_equal(bssid, bss->bssid))
return bss;
}
@@ -9213,7 +9289,7 @@
dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
struct wpa_bss_tmp_disallowed, list) {
- if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
+ if (ether_addr_equal(bss->bssid, tmp->bssid)) {
disallowed = tmp;
break;
}
@@ -9311,8 +9387,7 @@
dl_list_for_each(dso, &wpa_s->drv_signal_override,
struct driver_signal_override, list) {
- if (os_memcmp(wpa_s->bssid, dso->bssid,
- ETH_ALEN) != 0)
+ if (!ether_addr_equal(wpa_s->bssid, dso->bssid))
continue;
wpa_printf(MSG_DEBUG,
"Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
@@ -9357,7 +9432,7 @@
dl_list_for_each(dso, &wpa_s->drv_signal_override,
struct driver_signal_override, list) {
- if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
+ if (!ether_addr_equal(res->bssid, dso->bssid))
continue;
wpa_printf(MSG_DEBUG,
"Override driver scan signal level %d->%d for "
@@ -9379,7 +9454,7 @@
}
-static bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr)
+bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr)
{
int i;
@@ -9390,7 +9465,7 @@
if (!(wpa_s->valid_links & BIT(i)))
continue;
- if (os_memcmp(wpa_s->links[i].bssid, addr, ETH_ALEN) == 0)
+ if (ether_addr_equal(wpa_s->links[i].bssid, addr))
return true;
}
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index f6e4f83..d689441 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -982,9 +982,11 @@
# parameter uses following format: "<bgscan module name>:<module parameters>"
# Following bgscan modules are available:
# simple - Periodic background scans based on signal strength
+# send_btm_query > 0 means do this many BTM queries before attempting a scan.
# bgscan="simple:<short bgscan interval in seconds>:<signal strength threshold>:
-# <long interval>"
+# <long interval>[:<send_btm_query>]"
# bgscan="simple:30:-45:300"
+# bgscan="simple:30:-45:300:3"
# learn - Learn channels used by the network and try to avoid bgscans on other
# channels (experimental)
# bgscan="learn:<short bgscan interval in seconds>:<signal strength threshold>:
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 0890110..3a5f61c 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1,6 +1,6 @@
/*
* wpa_supplicant - Internal definitions
- * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2024, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -494,6 +494,7 @@
u8 bssid[ETH_ALEN];
enum beacon_report_detail report_detail;
struct bitfield *eids;
+ struct bitfield *ext_eids;
};
@@ -678,6 +679,13 @@
};
+struct ml_sta_link_info {
+ u8 link_id;
+ u8 bssid[ETH_ALEN];
+ u16 status;
+};
+
+
/**
* struct wpa_supplicant - Internal data for wpa_supplicant interface
*
@@ -740,11 +748,12 @@
u8 ap_mld_addr[ETH_ALEN];
u8 mlo_assoc_link_id;
u16 valid_links; /* bitmap of valid MLO link IDs */
- struct ml_sta_link_info {
+ struct {
u8 addr[ETH_ALEN];
u8 bssid[ETH_ALEN];
unsigned int freq;
struct wpa_bss *bss;
+ bool disabled;
} links[MAX_NUM_MLD_LINKS];
u8 *last_con_fail_realm;
size_t last_con_fail_realm_len;
@@ -1046,6 +1055,7 @@
bool ext_ml_auth;
int *sae_rejected_groups;
#endif /* CONFIG_SAE */
+ u16 assoc_auth_type;
} sme;
#endif /* CONFIG_SME */
@@ -1207,6 +1217,7 @@
struct wpa_ssid *bgscan_ssid;
const struct bgscan_ops *bgscan;
void *bgscan_priv;
+ int signal_threshold;
const struct autoscan_ops *autoscan;
struct wpa_driver_scan_params *autoscan_params;
@@ -1315,6 +1326,7 @@
u8 wnm_reply;
u8 wnm_num_neighbor_report;
u8 wnm_mode;
+ bool wnm_link_removal;
u16 wnm_dissoc_timer;
u8 wnm_bss_termination_duration[12];
struct neighbor_report *wnm_neighbor_report_elements;
@@ -1381,6 +1393,7 @@
unsigned int oci_freq_override_fils_assoc;
unsigned int oci_freq_override_wnm_sleep;
unsigned int disable_eapol_g2_tx;
+ int test_assoc_comeback_type;
#endif /* CONFIG_TESTING_OPTIONS */
struct wmm_ac_assoc_data *wmm_ac_assoc_info;
@@ -1567,8 +1580,24 @@
unsigned int multi_ap_ie:1;
unsigned int multi_ap_backhaul:1;
unsigned int multi_ap_fronthaul:1;
+
+#ifndef CONFIG_NO_ROBUST_AV
struct robust_av_data robust_av;
bool mscs_setup_done;
+ struct scs_robust_av_data scs_robust_av_req;
+ u8 scs_dialog_token;
+ struct dl_list active_scs_ids;
+ bool ongoing_scs_req;
+ u8 dscp_req_dialog_token;
+ u8 dscp_query_dialog_token;
+ unsigned int enable_dscp_policy_capa:1;
+ unsigned int connection_dscp:1;
+ unsigned int wait_for_dscp_req:1;
+#ifdef CONFIG_TESTING_OPTIONS
+ unsigned int disable_scs_support:1;
+ unsigned int disable_mscs_support:1;
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_NO_ROBUST_AV */
bool wps_scan_done; /* Set upon receiving scan results event */
bool supp_pbc_active; /* Set for interface when PBC is triggered */
@@ -1580,19 +1609,7 @@
unsigned int pasn_count;
struct pasn_auth *pasn_params;
#endif /* CONFIG_PASN */
- struct scs_robust_av_data scs_robust_av_req;
- u8 scs_dialog_token;
-#ifdef CONFIG_TESTING_OPTIONS
- unsigned int disable_scs_support:1;
- unsigned int disable_mscs_support:1;
-#endif /* CONFIG_TESTING_OPTIONS */
- struct dl_list active_scs_ids;
- bool ongoing_scs_req;
- u8 dscp_req_dialog_token;
- u8 dscp_query_dialog_token;
- unsigned int enable_dscp_policy_capa:1;
- unsigned int connection_dscp:1;
- unsigned int wait_for_dscp_req:1;
+
bool is_6ghz_enabled;
bool crossed_6ghz_dom;
bool last_scan_all_chan;
@@ -1609,6 +1626,12 @@
* owe_transition_search == 1 */
int *owe_trans_scan_freq;
#endif /* CONFIG_OWE */
+
+#ifdef CONFIG_NAN_USD
+ struct nan_de *nan_de;
+ struct wpa_radio_work *nan_usd_listen_work;
+ struct wpa_radio_work *nan_usd_tx_work;
+#endif /* CONFIG_NAN_USD */
};
@@ -1715,7 +1738,8 @@
enum frame_encryption encrypted);
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 wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const u8 **link_bssids);
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);
@@ -2015,5 +2039,6 @@
bool wpas_is_6ghz_supported(struct wpa_supplicant *wpa_s, bool only_enabled);
bool wpa_is_non_eht_scs_traffic_desc_supported(struct wpa_bss *bss);
+bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr);
#endif /* WPA_SUPPLICANT_I_H */
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 9804b91..111680c 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -418,7 +418,7 @@
const u8 *ie;
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
- if (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) != 0)
+ if (!ether_addr_equal(bss->bssid, wpa_s->bssid))
continue;
if (ssid == NULL ||
((bss->ssid_len == ssid->ssid_len &&
diff --git a/wpa_supplicant/wpas_module_tests.c b/wpa_supplicant/wpas_module_tests.c
index ce5398c..9e7a57c 100644
--- a/wpa_supplicant/wpas_module_tests.c
+++ b/wpa_supplicant/wpas_module_tests.c
@@ -17,9 +17,12 @@
static int wpas_bssid_ignore_module_tests(void)
{
struct wpa_supplicant wpa_s;
+ struct wpa_global global;
int ret = -1;
os_memset(&wpa_s, 0, sizeof(wpa_s));
+ os_memset(&global, 0, sizeof(global));
+ wpa_s.global = &global;
wpa_bssid_ignore_clear(&wpa_s);
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index cd94b64..81e11e7 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -295,8 +295,7 @@
if (ssid->bssid_set || new_ssid->bssid_set) {
if (ssid->bssid_set != new_ssid->bssid_set)
continue;
- if (os_memcmp(ssid->bssid, new_ssid->bssid, ETH_ALEN) !=
- 0)
+ if (!ether_addr_equal(ssid->bssid, new_ssid->bssid))
continue;
}
@@ -1062,7 +1061,7 @@
*/
#ifndef CONFIG_P2P
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
- if (os_memcmp(bssid, bss->bssid, ETH_ALEN) != 0)
+ if (!ether_addr_equal(bssid, bss->bssid))
continue;
os_free(ssid->ssid);
@@ -1812,7 +1811,7 @@
}
if (!ret && ssid->bssid_set &&
- os_memcmp(ssid->bssid, bss->bssid, ETH_ALEN) == 0) {
+ ether_addr_equal(ssid->bssid, bss->bssid)) {
/* allow wildcard SSID due to hardcoded BSSID match */
ret = 1;
}
@@ -1851,11 +1850,11 @@
const u8 *sel_uuid)
{
if (!ap->pbc_active ||
- os_memcmp(selected->bssid, ap->bssid, ETH_ALEN) == 0)
+ ether_addr_equal(selected->bssid, ap->bssid))
return false;
if (!is_zero_ether_addr(ssid->bssid) &&
- os_memcmp(ap->bssid, ssid->bssid, ETH_ALEN) != 0) {
+ !ether_addr_equal(ap->bssid, ssid->bssid)) {
wpa_printf(MSG_DEBUG, "WPS: Ignore another BSS " MACSTR
" in active PBC mode due to local BSSID limitation",
MAC2STR(ap->bssid));
@@ -2943,7 +2942,7 @@
for (i = 0; i < wpa_s->num_wps_ap; i++) {
struct wps_ap_info *ap = &wpa_s->wps_ap[i];
- if (os_memcmp(ap->bssid, bssid, ETH_ALEN) == 0)
+ if (ether_addr_equal(ap->bssid, bssid))
return ap;
}