[wpa_supplicant] cumilative patch from commit 3a5d1a7e6

Bug: 329004037
Test: Connect to open, WPA2, WPA3 and OWE
Test: Establish P2P connection
Test: Basic SoftAp tests
Test: Ran above tests on Pixel6
Test: Regression test (b/329003970)

BYPASS_INCLUSIVE_LANGUAGE_REASON=Merged from open source

3a5d1a7e6 NAN: USD in hostapd
e3f9ab3c3 NAN: USD in wpa_supplicant
9eb0bc1f0 NAN: Unsynchronized service discovery (USD)
f2ea8791c NAN: Protocol definitions
4f557c594 Add os_reltime helpers to work with milliseconds
0b5d370c0 DPP: Fix DPP Action frame check for EVENT_RX_MGMT events
8fa52a797 FT: Allow wpa_supplicant to be configured to prepend PMKR1Name
9929426b9 FT: Allow PMKIDs from AssocReq to be in EAPOL-Key msg 2/4
560389997 AP MLD: Handle EAPOL only on the association link
7ba039ba1 AP MLD: Do not allow disabling first interface affiliated with an AP MLD
9a47ede87 AP MLD: Add support for hostapd_cli to disable/enable AP MLD
0102c5c60 hostapd: Do not use prefix matching for ENABLE/RELOAD/DISABLE
03e89de47 AP MLD: Process link info when handling new STA event with driver SME
d3d59967a Handle both HT40+ and HT40- allowed consistently in channel check
e650fa4d7 ACS: Handle ACS channel selected event in specified link
0e91a86ec ACS: Add link id if operating as an AP MLD
f972420e8 AP MLD: Fix AID allocation for legacy STA
fe36750b3 Add QCA vendor command to disassociate with peer
9fe2970ff OpenSSL: Use library functions for HPKE when possible
14c5f401f Remove forgotted STAKey related functionality in EAPOL-Key Request
3f60fcdd8 FILS: Fix EAPOL-Key request generation
b27086e6e Discard EAPOL-Key request without Secure=1
096794088 Discard EAPOL-Key Request frames during 4-way handshake
8037c1ad6 Move Key Replay Counter checks for EAPOL-Key frames to helper functions
2c6147404 Check Key Descriptor Version value earlier in the process
bd1e07899 Reject undefined Key Descriptor Version values explicitly
fff69bba1 Use more generic checks for Key Descriptor Version 2 and 3
74a25a660 Remove always true check on EAPOL-Key message in authenticator
9e9afd956 Extend frequency configuration to handle 6 GHz channel 2
8677844db Add a QCA vendor attribute to determine QCA device
576f46250 P2P: Accept P2P SD response without TX status
16a22ef34 nl80211: Increase the hard scan timeout for initial attempt
f20ca22dc DFS: Print the random channel list entry selection in debug print
d88fe8fe5 DFS: Fix a typo in a debug message
e3fb9e6f2 Send actual BTM capability when the driver takes care of BSS selection
6c334d9f0 nl80211: Set allowed frequency list per link for AP MLD
42cd2376f Enhance QCA vendor interface with new SAR version numbers
5ae8838a0 Make test code easier for static analyzers
c03377cf2 SAE: Fix resource leak on reading a separate password file
348c047af ACS: More consistent checking of the best channel pointer
5d54bf6fb Fix error path on Key Data field decryption
a4d599a53 FT: Fix architecture for RxKH loading from a file
0b95d1346 OpenSSL: Fix a memory leak on an error path
456bfec47 Avoid uninitialized seq number in debug print for testing functionality
c17900278 tests: Fix a memory leak in a module test
7184e63ce dbus: Avoid memory leak on error when signaling PropertiesChanged
4037c0ac1 nl80211: Fix wiphy event handling when the driver is deinitialized
1c90c8d24 DPP: Avoid a potential use-after-free on an error path in AP
32940c7a4 DPP: Fix use-after-free in connection status reporting when using TCP
9456adeeb DPP3: Fix potential use-after-free on push button bootstrap info
e3d6fce84 EAP-SIM/AKA peer: Fix use-after-free for privacy identity
fd71cae6c nl80211: Fix memory leak on libnl nl_cb
2814dbd6d OpenSSL: Fix a memory leak in crypto_ec_key_parse_priv()
aa1aa289c AP MLD: Optimize struct mld_link_info size
93eab9f0f Mark hostapd_gen_probe_resp() static
512b92524 AP MLD: Reduce struct mld_link_info size
b91572b30 AP MLD: Fix RADIUS deinit
fa79e46c7 AP MLD: Use a helper function to set whether a STA is a non-AP MLD
6bda0aca8 AP MLD: Use a helper function to check if a STA is a non-AP MLD
ee9375fb3 tests: Association comeback mechanism in wpa_supplicant
33179cd29 SME: Handle PMF association comeback when not handled in driver
0ef4b1e1d D-Bus: Add a signal for HS2.0 terms and conditions
4e3f6b847 wlantest: Add test vectors for S1G BIP
542ccf00b FT: Add control interface command to show configured RxKHs
392114a17 FT: Add dynamic reload of RxKH definitions from file
e94a7d794 FT: Move RxKH configuration clearing into a helper function
c69ce778f Fix building against OpenSSL 3
5589d62c5 nl80211: Avoid NL80211_WPA_VERSION_3 on older kernel versions
5ff6a2749 Remove the MLD specific exception for distinguishing EAPOL-Key msg 2 and 4
2314a3569 Testing functionality for EAPOL-Key Key Data field encryption
4abc37e67 Support Key Data field decryption for EAPOL-Key msg 2/4 and 4/4
f591732af Supplicant side testing functionality for EAPOL-Key Key Data field
f7a903654 Extend mechanism to distinguish EAPOL-Key msg 2/4 from 4/4
3547ed403 Authenticator side testing functionality for EAPOL-Key Key Data field
38719f113 Verify center frequency seg0/seg1 mapping result before use
acea0654f Initialize the variables before using it in channel update
af6e21faa P2P: Fix a logical error of workaround of extended listen failure
abc239a0b Get rid of multiple MIN macros
5290523db Apply a symmetrical bias against moving away from higher bands
05474b34b Decrease cross-threshold roam difficulty with bgscan_simple
73f06af14 wpa_supplicant: Do not invalidate PMKSA cache for bssid_* updates
05c167eb0 MLD: Fail connection if ML Authentication frame could not be parsed
a80dcf0e2 MLD: Read the correct BSSID from the RNR
906dade4f RRM: Handle scan TSF BSSID matching in context of MLD
12cdeb501 nl80211: Print driver name in debug output
197b440c4 nl80211: Print kernel version in debug output
5ae010aae nl80211: Avoid sending unsupported attributes
7fec9e7bc nl80211: Retrieve maxattr via genl for nl80211
f13683720 nl80211: Pass wiphy events to all affected interfaces
f9b3ecb0a DPP: Work arouind missing Auth Confirm ACK for testing
655794898 RRM: Fix the parsing of the Extended Request subelement in beacon req
b9983b35d MSCS: Process unsolciited MSCS Response frames
b427683bf MSCS: Extend MSCS response handling
db036b534 MSCS: Use a define for the MSCS Descriptor element fixed field length
2d83d224f Use ether_addr_equal() to compare whether two MAC addresses are equal
58027cfec WPS: Fix authorized MAC removal
95123ab3b Introduce ether_addr_equal()
76616a46b RSN: Fix (B)IGTK MLO KDE length print
f048e6626 wpa_supplicant: Don't assign pointer to bool
e0a2b3222 Fix compiler warnings on supplicant build with PASN but no FILS
8e8964cdb AP: Fix compilation warning in hapd_pasn_update_params()
a2fd63964 build: bgscan_simple depends on WNM
628f28610 trace: Fix compilation issue due to using an undefined symbol
cbcd056ec AP: Fix a typo in function name
594f85e30 mesh: Set the mld_link_id to -1 when adding a station
f40a58833 nl80211: Fix AP MLD MAC address on auth retry
38711a011 AP MLD: Remove link stations on a new station authentication
c6f519ff1 AP: Support deauthenticate/disassociate with MLD
9c937c889 AP: Move hostapd_ml_get_assoc_sta() to shared
ea401c168 AP MLD: Fix station lookup in hostapd_ml_get_assoc_sta()
e9f75a352 AP: Unify code handling deauthentication/disassociation
a1d7a9e3b build: Properly grab the libpcsclite cflags
9569315de Disable _FORTIFY_SOURCE when building with -O0
2112f0572 AP MLD: Correctly set the BSS parameters change count in RNR
0120d052d nl80211: Add NL80211_ATTR_MLO_LINK_ID for NL80211_CMD_REMAIN_ON_CHANNEL
bef417152 GAS: Accept GAS response using AP MLD MAC address
29814ee96 Extend pmf_in_use() to be aware of affiliated links on non-AP MLD
6ea81f323 nl80211: More detailed debug print for Management frame TX
9ccfc0d51 AP MLD: MLD address conversion for hostapd_drv_send_action_addr3_ap()
febb51bf8 AP MLD: Fix Association Response frame ACK handling
07f44a7c4 AP MLD: Prefer STA entry that has sta->wpa_sm initialized
0aeeaaaf1 Add QCA vendor command for flow policy configuration
064c233d1 AP: Fix a regression in indoor 6 GHz AP determination
196d6c83b Limit throughput estimation for HE 80/160 MHz based on VHT info
12c0f8ae3 Limit throughput estimation for HE 40 MHz based on HT info
98f3bd26d ACS: Extend the 320 MHz support
e6f2494c3 hostapd: Add eht_bw320_offset configuration option
733de8568 ACS: Fix not selecting the best channel in the segment
4881accbb ACS: Add HT40- support in the 2.4 GHz band
47e89935c dbus: Use PHY parameters from dbus or config for the GroupAdd command
fae12c4b1 Fix P2P_GROUP_ADD handling of the persistent group parameters
0143cf42c Move parse_freq() to be a common helper function
e3570f5e1 dbus: Use current_bss to get correct group BSSID and frequency on client
b91113e05 Support all PSK AKMs in case of AP mode PSK offload
4efb0247a Update definitions to point to the current IEEE 802.11 standard
121ccadeb AP: A helper function for determining whether the AP is an SP AP
24baffc8b AP: Share a common helper function for determining length of TPE elements
150ee0c06 AP: Add an additional TPE element when needed
3cbb3ac3f AP: Add TPE element for Indoor standard power AP
bcad7fec6 AP: Publish the correct PSD value in RNR TBTT information field
7065e5242 AP: Add configuration options for 6 GHz TPE Tx power
ada9083ac AP: Update the HE regulatory information AP types for the 6 GHz band
2d4f90521 RRM: Add support for including extended ID elements in beacon report
c88c08f0c SME: Remove comment in missing ML links handling
41e65efa3 ctrl_iface: Fix newline in print_ml()
a3a34c0eb HS 2.0: Remove useless debug print in non-Hotspot 2.0 cases
615835626 AP: Use the MLD MAC address for SAE authentication failures and testing
4a973718d Split hostapd_eid_rnr_iface() into two functions
0b55b8da3 AP: Add testing option to indicate an AP is disabled
2249b9f77 nl80211: Include disabled links indication in association command
5927455b8 MLD: Add support for disabled APs
981e8c1e4 nl80211: Add link ID to the queue parameters configuration print
409ebaaa1 AP: Support overriding EHT operation puncturing mask
26ad0be4f AP: Allow hex format for puncturing bitmap
799115a8e AP: Fix EHT MCS size validation for received element
14d7b9e37 ctrl_iface: Don't return -1 when dumping BSS information
12a957434 nl80211: Fix AP deinit path (link removal) in error cases
6c3438eef nl80211: Fix AP deinit path in error cases
6b7bb1001 Add QCA vendor attribute for EHT SCS traffic description support
f8657ea03 Add QCA vendor command for reporting firmware page fault informatin
ee00bbd29 Support VLAN offload with SAE password based selection
e748e50c6 SAE passwords from a separate file
40b255882 PASN: Select the latest available BSS entry for a BSSID
09d57e5f8 MBSSID: Element ID values in increasing order in Non-Inheritance element
88984bbb9 MLD STA: Update SAE PWE derivation in hunting-and-pecking loop case
c8dd70cfb Fix Multiple BSSID element length calculation
618df655a Use sta->vlan_id when needed for VLAN offload
afd306cf7 nl80211: Remove send_and_recv_msgs()
7c2f67cea nl80211: Add send_and_recv_resp() helper
ab506d777 nl80211: Add send_and_recv_cmd() helper
c73f9cde8 nl80211: Remove send_and_recv_msgs_connect_handle()
d2e6a395c nl80211: Do not set socket owner for NL80211_CMD_LEAVE_IBSS
35e58b741 nl80211: Remove send_and_recv_msgs_owner()
9823f4305 nl80211: Move control port attribute adding into more accurate location
0d619df8b nl80211: Use bss->nl_connect unconditionally
da0d51fee nl80211: Use socket cb instead of global->nl_cb in send_and_recv()
84fdc8cd8 nl80211: Accept NL80211_CMD_FRAME events in global context
828311ef3 AP MLD: More careful checking of Multi-Link element length fields
38a5ed5fd AP MLD: Skip unknown Multi-Link element subelements
62141825f tests: PASN authentication using driver event as trigger
2ab56694f Split ap_sta_set_authorized() into two steps
da8a38fec Remove unused assignment from Country element generation
33b5fc076 PKCS#1: Do not use pointer value after freeing
231d86ef9 OpenSSL: Check EVP_MAC_update() return value more consistently
a92694b00 OpenSSL: Check EVP_CIPHER_CTX_set_padding() return value more consistently
88bc6711a TDLS: Avoid unnecessary copying of the Link Identifier element
656cf50d8 More consistent sta pointer checks in handle_assoc()
29f38ebcf ACS: Check whether iface->current_mode is NULL before use
7fa840309 WNM: Skip current connection BSS when disassociate imminent is set
7a873c81e AP MLD: Do not schedule disconnection on BSS TM Request link removal
ec70d14f7 AP: MLD: Extend BSS transition management request for link removal
09988c435 WNM: Accept link removal BSS TM Request
80810929a WNM: Handle BTM request with Link Removal Imminent field set to 1
31e025c03 AP: When sending Action frames, use the AP MLD MAC address if needed
54e6c56d2 AP: Use AP MLD MAC address for terminating MLO association
7ee12fca4 WNM: Allow frames from AP MLD
0546f0e1b WNM: Use correct address when configured as AP MLD
1efdba5fd Handle PMKSA flush in the driver for SAE/OWE offload cases
6a793c5f2 bgscan: Fix bgscan_init() stub declaration
0af4c1478 hostapd: Check the bridge if ioctl SIOCBRADDIF fails
1b9006a8c Use the link BSSID to resolve current BSS for whether to roam check
c4dac077b wpa_supplicant: Remove redundant CONFIG_WNM in wnm_sta.c
d43a49a66 Remove a spurious tab in hostapd_eid_rnr()
a28ea8e51 AP: Fix setting MLD Parameters subfield in RNR element
07525cd5e Fix HE enabling for IBSS and mesh
40410c04f AP MLD: Channel switch for specific link
1b448c865 hostapd configuration file update using control interface
7dd7ae965 DFS: Change vht_capab according to user requested bandwidth
8920e0390 P2P: Force clearing of p2p-send-action radio work on P2P_STOP_FIND
8e294c3a2 P2P: Recover from successfully requested, but not started, listen
ceb7f65dc bgscan: Allow simple bgscan to do BTM queries
a83d3132e WNM: Define BSS transition management reason values
7ee7b046a nl80211: Use attribute NL80211_ATTR_BSSID to scan for specific BSSID
5bbc9462a tests: Test driver association ML link rejection flow
32434aa68 AP: Always include WPA_STA_AUTHORIZED in station flags mask
174a8fc41 AP MLD: Do not modify flags for link stations
0b5d11165 Fix MBO build with GAS dependency
58116877b EHT: Fix updating center freq segment 0 index for HE and VHT
40b04b703 Document Tunnel-Password encoding for passphrase/PSK
37d122c2f KaY: Make debug output consistent
f0cb82351 EHT: Add configuration for the EHT default PE duration
5a47bbc36 Add QCA vendor command to query transmit power information
9c2d6c423 Add QCA vendor attributes for link id for HT-scan/ACS command
7b6705579 Add QCA vendor commands for SDWF
20c82a270 Add an option to remove WMM-AC
32b5f7f50 Add an option to remove Robust AV (SCS, MSCS, QoS Management)
6ed8eba00 Add an option to remove RRM and supported operating class indication
4b80ad119 Populate the new beacon hint event to wpa_msg()
d8cae2d02 nl80211: Do not allow off channel when frequency is not specified
bbb0d3a40 mesh: Add for_each_sta implementation in wpa_auth_callbacks
4f69b4a31 mesh: Fix PMKSA cache entry addition with external PMKSA management
0302c3ad2 trace: binutils replaces bfd_hostptr_t with uintptr_t
033634019 Ignore missing set_secure_ranging_ctx callback for testing purposes
d54d0d898 AP MLD: Handle DFS in correct link
f1fee0d1f AP MLD: Handle channel switch event in correct link
fb6598864 nl80211: Add link ID when setting BSS attributes for AP MLD
5487d8d9e nl80211: Specify link ID when sending Management frames
859cbc396 nl80211: Remove links when stopping AP MLD in hostapd
780e72cc1 AP MLD: Do not include empty MLO KDEs
ecd9ea0c8 AP MLD: Do not access WPA authenticator object if not valid
21e8fcc80 nl80211: Add support for handling MLO removed links
cd79d834b trace: Add TEST_FAIL_TAG macro to allow more narrow matching
781e87c41 trace: Allow multiple failures in one test
e62d351ce trace: Document function pattern prefixes
5545d995b trace: Share common implementation for TEST_FAIL and TEST_ALLOC_FAIL
7d901dc7e trace: Use an array of skipped function names
e9bdecce4 Share TEST_FAIL/TEST_ALLOC_FAIL/GET_FAIL/GET_ALLOC_FAIL handler
2c89ca922 wpa_supplicant: Use wpa_msg() in bssid_ignore.c
6fc2d1357 AP: Get rid of wpa_auth_pmksa_add3()
e99670420 AP: Handle re-association from a non-AP MLD
a18f8ee0f AP MLD: Use MLD MAC address for SA query and response when needed
b9c81e200 MLD: Use MLD MAC address for deauthentication
f60287e6c AP: Avoid setting same MLD and link address
e5917e2a5 scan: MLD: Include SSID in ML probe request
b29ac99d5 scan: Include AP MLD ID in ML probe request if needed
d64ec9414 AP MLD: Don't include AP MLD ID in Beacon frames
3bde81175 ML: Add basic handling of ML probe requests
ecb22ba12 AP: MLO: Add helper to iterate all links of an AP MLD
db2bc0364 AP: Add parsing of ML probe requests
82453a348 AP: Split Probe Response frame IE generation into a separate function
6b5e00a80 AP: Use a struct for Probe Response generation in/out params
3cd377eb5 MLD: Ignore failed links from association attempt
4a1cd7f54 nl80211: Report link specific association failures from the kernel
6ba9b9440 nl80211: Add support to parse out link from error reply
e6eebd0d5 MLD: Do not consider ignored BSSs for links when parsing RNR info
92d8d1d76 MLD: Add a TEST_FAIL to fail one link in an MLD association.
846e65c7c MLD: Return status code for links when rejecting association
5af986c75 MLD: Also mark links as failed after association failure
c55a272f6 EHT: Define status codes from IEEE P802.11be/D4.0
d95838b79 AP: Add support for testing ML link removal
73a6f5c37 AP MLD: Make BSS parameter change variable
9160540ec wpa_supplicant: Fix ml_ie_len type in wpa_bss_parse_basic_ml_element()
cb90aa3ac wpa_supplicant: Remove duplicate logic in wpas_ml_element()
74b688430 wpa_supplicant: Add config parameters for MLD testing
6220fb52e dbus: Increase XML buffer size for an interface introspection data
b3aafd5a8 common: Simplify and avoid confusing defragmentation API
0f7d15dd3 ieee802_11_defs: Fix EHT_ML_PRES_BM_PROBE_REQ_AP_MLD_ID
9ffebf758 SME: Drop old disassoc_while_authenticating workaround
645ec9b58 nl80211: Do a roundtrip to reset event supressions
c8b4ad70b tests: Set wpa_s->global for module tests
69ea73bfe nl80211: Update port authorized indication for MLO address
6f014c0d0 ACS: Add 320 MHz support for EHT
f0aea885f EHT: Fix HE Channel Center Freq Seg0/Seg1 for 6 GHz 320 MHz cases
07c03a655 EHT: Fix conditions for including EHT Operation Information field
01d95b75b SAE: prime_len means length in bytes not bits
a02585cef MBSSID: Use BIGTK from the transmitted BSS for beacon protection
a768556f7 Prefer SAE over PSK in WPA3-Personal transition mode cases
43184bf06 OWE: Optimize transition mode AP scan with owe_only=1 STA configuration
4ff287e92 P2P: Do not skip updating BSS table when frequency is changed
73b49016f Fix references to correct driver capability flag for PSK/OWE offloads
415839406 OpenSSL: Allow openssl_ciphers override with Suite B config on server
e9b13938a Add EHT mode support for ratemask configuration vendor command
239469eb1 Define new command in qca_tsf_cmd to get AP channel switch TSF time

Change-Id: I1540a39cd343b6fb9915fcc78e3f6bd2cb8eb0d9
Signed-off-by: Sunil Ravi <sunilravi@google.com>
diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c
index d226a8a..2fad3e1 100644
--- a/src/common/dpp_tcp.c
+++ b/src/common/dpp_tcp.c
@@ -563,7 +563,7 @@
 	struct dpp_connection *conn;
 
 	dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) {
-		if (os_memcmp(src, conn->mac_addr, ETH_ALEN) == 0)
+		if (ether_addr_equal(src, conn->mac_addr))
 			return conn;
 		if ((type == DPP_PA_PKEX_EXCHANGE_RESP ||
 		     type == DPP_PA_AUTHENTICATION_RESP) &&
@@ -661,7 +661,7 @@
 	struct dpp_connection *conn;
 
 	dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) {
-		if (os_memcmp(src, conn->mac_addr, ETH_ALEN) == 0)
+		if (ether_addr_equal(src, conn->mac_addr))
 			return conn;
 	}
 
@@ -2601,7 +2601,8 @@
 }
 
 
-static void dpp_tcp_send_conn_status_msg(struct dpp_connection *conn,
+static void dpp_tcp_send_conn_status_msg(struct dpp_global *dpp,
+					 struct dpp_connection *conn,
 					 enum dpp_status_error result,
 					 const u8 *ssid, size_t ssid_len,
 					 const char *channel_list)
@@ -2609,6 +2610,7 @@
 	struct dpp_authentication *auth = conn->auth;
 	int res;
 	struct wpabuf *msg;
+	struct dpp_connection *c;
 
 	auth->conn_status_requested = 0;
 
@@ -2627,8 +2629,16 @@
 		return;
 	}
 
-	/* This exchange will be terminated in the TX status handler */
-	conn->on_tcp_tx_complete_remove = 1;
+	/* conn might have been removed during the dpp_tcp_send_msg() call, so
+	 * need to check that it is still present before modifying it. */
+	dl_list_for_each(c, &dpp->tcp_init, struct dpp_connection, list) {
+		if (conn == c) {
+			/* This exchange will be terminated in the TX status
+			 * handler */
+			conn->on_tcp_tx_complete_remove = 1;
+			break;
+		}
+	}
 }
 
 
@@ -2641,7 +2651,7 @@
 
 	dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) {
 		if (conn->auth && conn->auth->conn_status_requested) {
-			dpp_tcp_send_conn_status_msg(conn, result, ssid,
+			dpp_tcp_send_conn_status_msg(dpp, conn, result, ssid,
 						     ssid_len, channel_list);
 			break;
 		}
diff --git a/src/common/gas_server.c b/src/common/gas_server.c
index 745a13f..1075500 100644
--- a/src/common/gas_server.c
+++ b/src/common/gas_server.c
@@ -352,7 +352,7 @@
 	dl_list_for_each(response, &gas->responses, struct gas_server_response,
 			 list) {
 		if (response->dialog_token != dialog_token ||
-		    os_memcmp(sa, response->dst, ETH_ALEN) != 0)
+		    !ether_addr_equal(sa, response->dst))
 			continue;
 		gas_server_handle_rx_comeback_req(response);
 		return 0;
@@ -470,7 +470,7 @@
 	dl_list_for_each(response, &gas->responses, struct gas_server_response,
 			 list) {
 		if (response->dialog_token != dialog_token ||
-		    os_memcmp(dst, response->dst, ETH_ALEN) != 0)
+		    !ether_addr_equal(dst, response->dst))
 			continue;
 		gas_server_handle_tx_status(response, ack);
 		return;
diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c
index 57b5a8e..f45d2e9 100644
--- a/src/common/hw_features_common.c
+++ b/src/common/hw_features_common.c
@@ -448,6 +448,7 @@
 		} else {
 			int freq1, freq2 = 0;
 			int bw = center_idx_to_bw_6ghz(center_segment0);
+			int opclass;
 
 			if (bw < 0) {
 				wpa_printf(MSG_ERROR,
@@ -455,7 +456,10 @@
 				return -1;
 			}
 
-			freq1 = ieee80211_chan_to_freq(NULL, 131,
+			/* The 6 GHz channel 2 uses a different operating class
+			 */
+			opclass = center_segment0 == 2 ? 136 : 131;
+			freq1 = ieee80211_chan_to_freq(NULL, opclass,
 						       center_segment0);
 			if (freq1 < 0) {
 				wpa_printf(MSG_ERROR,
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index dbe7b29..08ba45b 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -1012,7 +1012,7 @@
 			continue;
 		}
 
-		if (sub_elem_len < 3) {
+		if (sub_elem_len < 5) {
 			if (show_errors)
 				wpa_printf(MSG_DEBUG,
 					   "MLD: error: sub_elem_len=%zu < 5",
@@ -1081,7 +1081,8 @@
 			non_inherit_len -= 1 + non_inherit[0];
 			non_inherit += 1 + non_inherit[0];
 
-			if (non_inherit_len < 1UL + non_inherit[0]) {
+			if (non_inherit_len < 1UL ||
+			    non_inherit_len < 1UL + non_inherit[0]) {
 				if (show_errors)
 					wpa_printf(MSG_DEBUG,
 						   "MLD: Invalid inheritance");
@@ -2507,35 +2508,6 @@
 
 
 /**
- * get_ie_nth - Fetch a specified information element from IEs buffer
- * @ies: Information elements buffer
- * @len: Information elements buffer length
- * @eid: Information element identifier (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 IEs
- * buffer or %NULL in case the element is not found.
- */
-const u8 * get_ie_nth(const u8 *ies, size_t len, u8 eid, int nth)
-{
-	const struct element *elem;
-	int sofar = 0;
-
-	if (!ies)
-		return NULL;
-
-	for_each_element_id(elem, eid, ies, len) {
-		sofar++;
-		if (sofar == nth)
-			return &elem->id;
-	}
-
-	return NULL;
-}
-
-
-/**
  * get_ie_ext - Fetch a specified extended information element from IEs buffer
  * @ies: Information elements buffer
  * @len: Information elements buffer length
@@ -2874,6 +2846,21 @@
 }
 
 
+bool is_same_band(int freq1, int freq2)
+{
+	if (IS_2P4GHZ(freq1) && IS_2P4GHZ(freq2))
+		return true;
+
+	if (IS_5GHZ(freq1) && IS_5GHZ(freq2))
+		return true;
+
+	if (is_6ghz_freq(freq1) && is_6ghz_freq(freq2))
+		return true;
+
+	return false;
+}
+
+
 int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
 				    size_t nei_rep_len)
 {
@@ -3212,8 +3199,39 @@
 }
 
 
-struct wpabuf * ieee802_11_defrag_data(const u8 *data, size_t len,
-				       bool ext_elem)
+/**
+ * chwidth_freq2_to_ch_width - Determine channel width as enum oper_chan_width
+ * @chwidth: Channel width integer
+ * @freq2: Value for frequency 2. 0 is not used
+ * Returns: enum oper_chan_width, -1 on failure
+ */
+int chwidth_freq2_to_ch_width(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;
+	}
+}
+
+
+struct wpabuf * ieee802_11_defrag(const u8 *data, size_t len, bool ext_elem)
 {
 	struct wpabuf *buf;
 	const u8 *pos, *end = data + len;
@@ -3253,43 +3271,42 @@
 }
 
 
-struct wpabuf * ieee802_11_defrag(struct ieee802_11_elems *elems,
-				  u8 eid, u8 eid_ext)
+const u8 * get_ml_ie(const u8 *ies, size_t len, u8 type)
 {
-	const u8 *data;
-	size_t len;
+	const struct element *elem;
 
-	/*
-	 * TODO: Defragmentation mechanism can be supported for all IEs. For now
-	 * handle only those that are used (or use ieee802_11_defrag_data()).
-	 */
-	switch (eid) {
-	case WLAN_EID_EXTENSION:
-		switch (eid_ext) {
-		case WLAN_EID_EXT_FILS_HLP_CONTAINER:
-			data = elems->fils_hlp;
-			len = elems->fils_hlp_len;
-			break;
-		case WLAN_EID_EXT_WRAPPED_DATA:
-			data = elems->wrapped_data;
-			len = elems->wrapped_data_len;
-			break;
-		default:
-			wpa_printf(MSG_DEBUG,
-				   "Defragmentation not supported. eid_ext=%u",
-				   eid_ext);
-			return NULL;
-		}
-		break;
-	default:
-		wpa_printf(MSG_DEBUG,
-			   "Defragmentation not supported. eid=%u", eid);
+	if (!ies)
 		return NULL;
+
+	for_each_element_extid(elem, WLAN_EID_EXT_MULTI_LINK, ies, len) {
+		if (elem->datalen >= 2 &&
+		    (elem->data[1] & MULTI_LINK_CONTROL_TYPE_MASK) == type)
+			return &elem->id;
 	}
 
-	return ieee802_11_defrag_data(data, len, true);
+	return NULL;
 }
 
+
+const u8 * get_basic_mle_mld_addr(const u8 *buf, size_t len)
+{
+	const size_t mld_addr_pos =
+		2 /* Control field */ +
+		1 /* Common Info Length field */;
+	const size_t fixed_len = mld_addr_pos +
+		ETH_ALEN /* MLD MAC Address field */;
+
+	if (len < fixed_len)
+		return NULL;
+
+	if ((buf[0] & MULTI_LINK_CONTROL_TYPE_MASK) !=
+	    MULTI_LINK_CONTROL_TYPE_BASIC)
+		return NULL;
+
+	return &buf[mld_addr_pos];
+}
+
+
 /* Parse HT capabilities to get maximum number of supported spatial streams */
 static int parse_ht_mcs_set_for_max_nss(
 				struct ieee80211_ht_capabilities *htcaps,
@@ -3419,6 +3436,7 @@
 	return supported_width;
 }
 
+
 /*
  * Parse VHT operation info fields to get operation channel width
  * note that VHT operation info fields could come from VHT operation IE
@@ -3453,6 +3471,7 @@
 	return channel_width;
 }
 
+
 /* Parse 6GHz operation info fields to get operation channel width */
 static enum chan_width get_6ghz_operation_channel_width(
 				struct ieee80211_6ghz_operation_info * six_ghz_oper_info)
@@ -3525,6 +3544,7 @@
 	return channel_width;
 }
 
+
 /* Parse EHT operation IE to get EHT operation channel width */
 static enum chan_width get_eht_operation_channel_width(
 				struct ieee80211_eht_operation *eht_oper,
@@ -3558,6 +3578,7 @@
 	return channel_width;
 }
 
+
 /* Parse HT/VHT/HE operation IEs to get operation channel width */
 enum chan_width get_operation_channel_width(struct ieee802_11_elems *elems)
 {
@@ -3594,6 +3615,8 @@
 	return channel_width;
 }
 
+
+
 /*
  * Get STA operation channel width from AP's operation channel width and
  *  STA's supported channel width
@@ -3615,78 +3638,6 @@
 	return ap_operation_chan_width;
 }
 
-const u8 * get_ml_ie(const u8 *ies, size_t len, u8 type)
-{
-	const struct element *elem;
-
-	if (!ies)
-		return NULL;
-
-	for_each_element_extid(elem, WLAN_EID_EXT_MULTI_LINK, ies, len) {
-		if (elem->datalen >= 2 &&
-		    (elem->data[1] & MULTI_LINK_CONTROL_TYPE_MASK) == type)
-			return &elem->id;
-	}
-
-	return NULL;
-}
-
-
-const u8 * get_basic_mle_mld_addr(const u8 *buf, size_t len)
-{
-	const size_t mld_addr_pos =
-		2 /* Control field */ +
-		1 /* Common Info Length field */;
-	const size_t fixed_len = mld_addr_pos +
-		ETH_ALEN /* MLD MAC Address field */;
-
-	if (len < fixed_len)
-		return NULL;
-
-	if ((buf[0] & MULTI_LINK_CONTROL_TYPE_MASK) !=
-	    MULTI_LINK_CONTROL_TYPE_BASIC)
-		return NULL;
-
-	return &buf[mld_addr_pos];
-}
-
-
-struct wpabuf * ieee802_11_defrag_mle(struct ieee802_11_elems *elems, u8 type)
-{
-	const u8 *data;
-	size_t len;
-
-	switch (type) {
-	case MULTI_LINK_CONTROL_TYPE_BASIC:
-		data = elems->basic_mle;
-		len = elems->basic_mle_len;
-		break;
-	case MULTI_LINK_CONTROL_TYPE_PROBE_REQ:
-		data = elems->probe_req_mle;
-		len = elems->probe_req_mle_len;
-		break;
-	case MULTI_LINK_CONTROL_TYPE_RECONF:
-		data = elems->reconf_mle;
-		len = elems->reconf_mle_len;
-		break;
-	case MULTI_LINK_CONTROL_TYPE_TDLS:
-		data = elems->tdls_mle;
-		len = elems->tdls_mle_len;
-		break;
-	case MULTI_LINK_CONTROL_TYPE_PRIOR_ACCESS:
-		data = elems->prior_access_mle;
-		len = elems->prior_access_mle_len;
-		break;
-	default:
-		wpa_printf(MSG_DEBUG,
-			   "Defragmentation not supported for Multi-Link element type=%u",
-			   type);
-		return NULL;
-	}
-
-	return ieee802_11_defrag_data(data, len, true);
-}
-
 
 unsigned int is_ap_t2lm_negotiation_supported(const u8 *mle, size_t mle_len)
 {
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index 6f4fe80..60260e5 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -261,7 +261,6 @@
 extern size_t global_op_class_size;
 
 const u8 * get_ie(const u8 *ies, size_t len, u8 eid);
-const u8 * get_ie_nth(const u8 *ies, size_t len, u8 eid, int nth);
 const u8 * get_ie_ext(const u8 *ies, size_t len, u8 ext);
 const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type);
 
@@ -284,6 +283,10 @@
 bool is_6ghz_psc_frequency(int freq);
 int get_6ghz_sec_channel(int channel);
 
+bool is_same_band(int freq1, int freq2);
+#define IS_2P4GHZ(n) (n >= 2412 && n <= 2484)
+#define IS_5GHZ(n) (n > 4000 && n < 5895)
+
 int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
 				    size_t nei_rep_len);
 
@@ -293,6 +296,7 @@
 bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab);
 int op_class_to_bandwidth(u8 op_class);
 enum oper_chan_width op_class_to_ch_width(u8 op_class);
+int chwidth_freq2_to_ch_width(int chwidth, int freq2);
 
 /* element iteration helpers */
 #define for_each_element(_elem, _data, _datalen)			\
@@ -350,11 +354,7 @@
 int ieee802_edmg_is_allowed(struct ieee80211_edmg_config allowed,
 			    struct ieee80211_edmg_config requested);
 
-struct wpabuf * ieee802_11_defrag_data(const u8 *data, size_t len,
-				       bool ext_elem);
-struct wpabuf * ieee802_11_defrag(struct ieee802_11_elems *elems,
-				  u8 eid, u8 eid_ext);
-struct wpabuf * ieee802_11_defrag_mle(struct ieee802_11_elems *elems, u8 type);
+struct wpabuf * ieee802_11_defrag(const u8 *data, size_t len, bool ext_elem);
 const u8 * get_ml_ie(const u8 *ies, size_t len, u8 type);
 const u8 * get_basic_mle_mld_addr(const u8 *buf, size_t len);
 
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index a895f9c..619aa19 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -24,6 +24,13 @@
 #define WLAN_FC_ISWEP		0x4000
 #define WLAN_FC_HTC		0x8000
 
+#define WLAN_FC_S1G_BEACON_NEXT_TBTT	0x0100
+#define WLAN_FC_S1G_BEACON_COMP_SSID	0x0200
+#define WLAN_FC_S1G_BEACON_ANO		0x0400
+#define WLAN_FC_S1G_BEACON_BSS_BW	0x3800
+#define WLAN_FC_S1G_BEACON_SECURITY	0x4000
+#define WLAN_FC_S1G_BEACON_AP_PM	0x8000
+
 #define WLAN_FC_GET_TYPE(fc)	(((fc) & 0x000c) >> 2)
 #define WLAN_FC_GET_STYPE(fc)	(((fc) & 0x00f0) >> 4)
 
@@ -36,6 +43,7 @@
 #define WLAN_FC_TYPE_MGMT		0
 #define WLAN_FC_TYPE_CTRL		1
 #define WLAN_FC_TYPE_DATA		2
+#define WLAN_FC_TYPE_EXT		3
 
 /* management */
 #define WLAN_FC_STYPE_ASSOC_REQ		0
@@ -77,6 +85,10 @@
 #define WLAN_FC_STYPE_QOS_CFPOLL	14
 #define WLAN_FC_STYPE_QOS_CFACKPOLL	15
 
+/* extension */
+#define WLAN_FC_STYPE_DMG_BEACON	0
+#define WLAN_FC_STYPE_S1G_BEACON	1
+
 /* Authentication algorithms */
 #define WLAN_AUTH_OPEN			0
 #define WLAN_AUTH_SHARED_KEY		1
@@ -107,7 +119,7 @@
 #define WLAN_CAPABILITY_DELAYED_BLOCK_ACK BIT(14)
 #define WLAN_CAPABILITY_IMM_BLOCK_ACK BIT(15)
 
-/* Status codes (IEEE Std 802.11-2016, 9.4.1.9, Table 9-46) */
+/* Status codes (IEEE Std 802.11-2020, 9.4.1.9, Table 9-50) */
 #define WLAN_STATUS_SUCCESS 0
 #define WLAN_STATUS_UNSPECIFIED_FAILURE 1
 #define WLAN_STATUS_TDLS_WAKEUP_ALTERNATE 2
@@ -209,11 +221,20 @@
 #define WLAN_STATUS_DENIED_HE_NOT_SUPPORTED 124
 #define WLAN_STATUS_SAE_HASH_TO_ELEMENT 126
 #define WLAN_STATUS_SAE_PK 127
+#define WLAN_STATUS_DENIED_STA_AFF_WITH_MLD_WITH_EXISTING_ASSOC 130
+#define WLAN_STATUS_EPCS_DENIED_UNAUTHORIZED 131
+#define WLAN_STATUS_EPCS_DENIED 132
+#define WLAN_STATUS_DENIED_TID_TO_LINK_MAPPING 133
+#define WLAN_STATUS_PREFERRED_TID_TO_LINK_MAPPING_SUGGESTED 134
+#define WLAN_STATUS_DENIED_EHT_NOT_SUPPORTED 135
 #define WLAN_STATUS_INVALID_PUBLIC_KEY 136
 #define WLAN_STATUS_PASN_BASE_AKMP_FAILED 137
 #define WLAN_STATUS_OCI_MISMATCH 138
+#define WLAN_STATUS_DENIED_TX_LINK_NOT_ACCEPTED 139
+#define WLAN_STATUS_EPCS_DENIED_VERIFICATION_FAILURE 140
+#define WLAN_STATUS_DENIED_OPERATION_PARAMETER_UPDATE 141
 
-/* Reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45) */
+/* Reason codes (IEEE Std 802.11-2020, 9.4.1.7, Table 9-90) */
 #define WLAN_REASON_UNSPECIFIED 1
 #define WLAN_REASON_PREV_AUTH_NOT_VALID 2
 #define WLAN_REASON_DEAUTH_LEAVING 3
@@ -277,7 +298,7 @@
 #define WLAN_REASON_MESH_CHANNEL_SWITCH_UNSPECIFIED 66
 
 
-/* Information Element IDs (IEEE Std 802.11-2016, 9.4.2.1, Table 9-77) */
+/* Element IDs (IEEE Std 802.11-2020, 9.4.2.1, Table 9-92) */
 #define WLAN_EID_SSID 0
 #define WLAN_EID_SUPP_RATES 1
 #define WLAN_EID_DS_PARAMS 3
@@ -599,7 +620,7 @@
 /* Multiple BSSID element subelements */
 #define WLAN_MBSSID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE 0
 
-/* Action frame categories (IEEE Std 802.11-2016, 9.4.1.11, Table 9-76) */
+/* Action frame categories (IEEE Std 802.11-2020, 9.4.1.11, Table 9-51) */
 #define WLAN_ACTION_SPECTRUM_MGMT 0
 #define WLAN_ACTION_QOS 1
 #define WLAN_ACTION_DLS 2
@@ -640,7 +661,7 @@
 #define WLAN_ACTION_VENDOR_SPECIFIC 127
 /* Note: 128-255 used to report errors by setting category | 0x80 */
 
-/* Public action codes (IEEE Std 802.11-2016, 9.6.8.1, Table 9-307) */
+/* Public action codes (IEEE Std 802.11-2020, 9.6.7.1, Table 9-364) */
 #define WLAN_PA_20_40_BSS_COEX 0
 #define WLAN_PA_DSE_ENABLEMENT 1
 #define WLAN_PA_DSE_DEENABLEMENT 2
@@ -691,8 +712,8 @@
 #define WLAN_VHT_ACTION_GROUP_ID_MGMT 1
 #define WLAN_VHT_ACTION_OPMODE_NOTIF 2
 
-/* Protected Dual of Public Action frames (IEEE Std 802.11-2016, 9.6.11,
- * Table 9-332) */
+/* Protected Dual of Public Action frames (IEEE Std 802.11-2020, 9.6.10,
+ * Table 9-404) */
 #define WLAN_PROT_DSE_ENABLEMENT 1
 #define WLAN_PROT_DSE_DEENABLEMENT 2
 #define WLAN_PROT_EXT_CSA 4
@@ -720,7 +741,7 @@
 #define WLAN_PROT_NETWORK_CHANNEL_CONTROL 30
 #define WLAN_PROT_WHITE_SPACE_MAP_ANNOUNCEMENT 31
 
-/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */
+/* SA Query Action frame (IEEE Std 802.11-2020, 9.6.9) */
 #define WLAN_SA_QUERY_REQUEST 0
 #define WLAN_SA_QUERY_RESPONSE 1
 
@@ -753,7 +774,7 @@
 #define WLAN_PROT_FTM_REPORT 3
 
 /* Radio Measurement capabilities (from RM Enabled Capabilities element)
- * IEEE Std 802.11-2016, 9.4.2.45, Table 9-157 */
+ * IEEE Std 802.11-2020, 9.4.2.44, Table 9-179 */
 /* byte 1 (out of 5) */
 #define WLAN_RRM_CAPS_LINK_MEASUREMENT BIT(0)
 #define WLAN_RRM_CAPS_NEIGHBOR_REPORT BIT(1)
@@ -766,8 +787,8 @@
 #define WLAN_RRM_CAPS_FTM_RANGE_REPORT BIT(2)
 
 /*
- * IEEE P802.11-REVmc/D5.0, 9.4.2.21.19 (Fine Timing Measurement Range
- * request) - Minimum AP count
+ * IEEE Std 802.11-2020, 9.4.2.20.19 (Fine Timing Measurement Range
+ * request) - Minimum AP Count
  */
 #define WLAN_RRM_RANGE_REQ_MAX_MIN_AP 15
 
@@ -776,7 +797,8 @@
 #define WLAN_TIMEOUT_KEY_LIFETIME 2
 #define WLAN_TIMEOUT_ASSOC_COMEBACK 3
 
-/* Interworking element (IEEE 802.11u) - Access Network Options */
+/* Interworking element (IEEE Std 802.11-2020, 9.4.2.91) -
+ * Access Network Options */
 #define INTERWORKING_ANO_ACCESS_NETWORK_MASK 0x0f
 #define INTERWORKING_ANO_INTERNET 0x10
 #define INTERWORKING_ANO_ASRA 0x20
@@ -792,7 +814,7 @@
 #define INTERWORKING_ANT_TEST 6
 #define INTERWORKING_ANT_WILDCARD 15
 
-/* Advertisement Protocol ID definitions (IEEE Std 802.11-2016, Table 9-215) */
+/* Advertisement Protocol ID definitions (IEEE Std 802.11-2020, Table 9-237) */
 enum adv_proto_id {
 	ACCESS_NETWORK_QUERY_PROTOCOL = 0,
 	MIH_INFO_SERVICE = 1,
@@ -802,8 +824,7 @@
 	ADV_PROTO_VENDOR_SPECIFIC = 221
 };
 
-/* Access Network Query Protocol info ID definitions (IEEE Std 802.11-2016,
- * Table 9-271; P802.11ai) */
+/* ANQP-element definitions (IEEE Std 802.11-2020, Table 9-331) */
 enum anqp_info_id {
 	ANQP_QUERY_LIST = 256,
 	ANQP_CAPABILITY_LIST = 257,
@@ -878,7 +899,7 @@
 #define S1G_ACT_TWT_INFORMATION      11
 
 /*
- * IEEE P802.11-REVmc/D5.0 Table 9-81 - Measurement type definitions for
+ * IEEE Std 802.11-2020, Table 9-98 - Measurement type definitions for
  * measurement requests
  */
 enum measure_type {
@@ -902,7 +923,7 @@
 	MEASURE_TYPE_MEASURE_PAUSE = 255,
 };
 
-/* IEEE Std 802.11-2012 Table 8-71 - Location subject definition */
+/* IEEE Std 802.11-2020, Table 9-110 - Location Subject field definition */
 enum location_subject {
 	LOCATION_SUBJECT_LOCAL = 0,
 	LOCATION_SUBJECT_REMOTE = 1,
@@ -910,7 +931,7 @@
 };
 
 /*
- * IEEE P802.11-REVmc/D5.0 Table 9-94 - Optional subelement IDs for LCI request
+ * IEEE Std 802.11-2020, Table 9-111 - Optional subelement IDs for LCI request
  */
 enum lci_req_subelem {
 	LCI_REQ_SUBELEM_AZIMUTH_REQ = 1,
@@ -945,6 +966,23 @@
 
 #define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr))
 
+struct ieee80211_hdr_s1g_beacon {
+	le16 frame_control;
+	le16 duration_id;
+	u8 sa[6];
+	u8 timestamp[4];
+	u8 change_seq[1];
+	/* followed by:
+	 *   'u8 next_tbtt[3];' if the Next TBTT Present field in the
+	 *			Frame Control field is 1
+	 *   'u8 compressed_ssid[4];' if the Compressed SSID Present field in
+	 *			the Frame Control is 1
+	 *   'u8 ano[1];' if the ANO field in the Frame Control field is 1
+	 */
+} STRUCT_PACKED;
+
+#define IEEE80211_HDRLEN_S1G_BEACON (sizeof(struct ieee80211_hdr_s1g_beacon))
+
 #define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4))
 
 struct ieee80211_mgmt {
@@ -1396,7 +1434,11 @@
 #define WFD_OUI_TYPE 10
 #define HS20_IE_VENDOR_TYPE 0x506f9a10
 #define OSEN_IE_VENDOR_TYPE 0x506f9a12
+#define NAN_IE_VENDOR_TYPE 0x506f9a13
+#define NAN_SDF_VENDOR_TYPE 0x506f9a13
+#define NAN_OUI_TYPE 0x13
 #define MBO_IE_VENDOR_TYPE 0x506f9a16
+#define NAN_NAF_VENDOR_TYPE 0x506f9a18
 #define MBO_OUI_TYPE 22
 #define OWE_IE_VENDOR_TYPE 0x506f9a1c
 #define OWE_OUI_TYPE 28
@@ -1882,8 +1924,9 @@
 #define WNM_BSS_TM_REQ_DISASSOC_IMMINENT BIT(2)
 #define WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED BIT(3)
 #define WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT BIT(4)
+#define WNM_BSS_TM_REQ_LINK_REMOVAL_IMMINENT BIT(5)
 
-/* IEEE Std 802.11-2012 - Table 8-253 */
+/* IEEE Std 802.11-2020, Table 9-428 (BTM status code definitions) */
 enum bss_trans_mgmt_status_code {
 	WNM_BSS_TM_ACCEPT = 0,
 	WNM_BSS_TM_REJECT_UNSPECIFIED = 1,
@@ -1896,9 +1939,36 @@
 	WNM_BSS_TM_REJECT_LEAVING_ESS = 8
 };
 
+/* BSS transition management reasons
+ * IEEE Std 802.11-2020, Table 9-198 (Transition and Transition Query reasons)
+ */
+enum bss_trans_mgmt_reason {
+	WNM_TRANSITION_REASON_UNSPECIFIED = 0,
+	WNM_TRANSITION_REASON_EXCESSIVE_FRAME_LOSS = 1,
+	WNM_TRANSITION_REASON_EXCESSIVE_DELAY = 2,
+	WNM_TRANSITION_REASON_INSUFFICIENT_QOS = 3,
+	WNM_TRANSITION_REASON_FIRST_ESS_ASSOC = 4,
+	WNM_TRANSITION_REASON_LOAD_BALANCING = 5,
+	WNM_TRANSITION_REASON_BETTER_AP_FOUND = 6,
+	WNM_TRANSITION_REASON_DEAUTH_FROM_PREV_AP = 7,
+	WNM_TRANSITION_REASON_AP_FAILED_EAP = 8,
+	WNM_TRANSITION_REASON_AP_FAILED_4WAY_HS = 9,
+	WNM_TRANSITION_REASON_RX_TOO_MANY_REPLAYS = 10,
+	WNM_TRANSITION_REASON_RX_TOO_MANY_MIC_FAILURES = 11,
+	WNM_TRANSITION_REASON_EXCEEDED_MAX_RETRANS = 12,
+	WNM_TRANSITION_REASON_RX_TOO_MANY_BC_DISASSOC = 13,
+	WNM_TRANSITION_REASON_RX_TOO_MANY_BC_DEAUTH = 14,
+	WNM_TRANSITION_REASON_PREV_TRANSITION_FAILED = 15,
+	WNM_TRANSITION_REASON_LOW_RSSI = 16,
+	WNM_TRANSITION_REASON_ROAM_FROM_NON_802_11 = 17,
+	WNM_TRANSITION_REASON_TRANSITION_DUE_TO_BTM_REQ = 18,
+	WNM_TRANSITION_REASON_PREF_TRANSITION_CANDIDATE_LIST = 19,
+	WNM_TRANSITION_REASON_LEAVING_ESS = 20,
+};
+
 /*
- * IEEE P802.11-REVmc/D5.0 Table 9-150 - Optional subelement IDs for
- * neighbor report
+ * IEEE Std 802.11-2020, Table 9-173 - Optional subelement IDs for
+ * Neighbor Report
  */
 #define WNM_NEIGHBOR_TSF                         1
 #define WNM_NEIGHBOR_CONDENSED_COUNTRY_STRING    2
@@ -1925,7 +1995,7 @@
 	QOS_QOS_MAP_CONFIG = 4,
 };
 
-/* IEEE Std 802.11-2012, 8.4.2.62 20/40 BSS Coexistence element */
+/* IEEE Std 802.11-2020, 9.4.2.59 (20/40 BSS Coexistence element) */
 #define WLAN_20_40_BSS_COEX_INFO_REQ            BIT(0)
 #define WLAN_20_40_BSS_COEX_40MHZ_INTOL         BIT(1)
 #define WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ     BIT(2)
@@ -1973,7 +2043,7 @@
 	WNM_SLEEP_SUBELEM_BIGTK = 2,
 };
 
-/* WNM notification type (IEEE P802.11-REVmd/D3.0, Table 9-430) */
+/* WNM notification type (IEEE Std 802.11-2020, Table 9-431) */
 enum wnm_notification_Type {
 	WNM_NOTIF_TYPE_FIRMWARE_UPDATE = 0,
 	WNM_NOTIF_TYPE_BEACON_PROTECTION_FAILURE = 2,
@@ -2049,7 +2119,7 @@
 
 #define RRM_CAPABILITIES_IE_LEN 5
 
-/* IEEE Std 802.11-2012, 8.5.7.4 - Link Measurement Request frame format */
+/* IEEE Std 802.11-2020, 9.6.6.4 - Link Measurement Request frame format */
 struct rrm_link_measurement_request {
 	u8 dialog_token;
 	s8 tx_power;
@@ -2057,7 +2127,7 @@
 	u8 variable[0];
 } STRUCT_PACKED;
 
-/* IEEE Std 802.11-2012, 8.5.7.5 - Link Measurement Report frame format */
+/* IEEE Std 802.11-2020, 9.6.6.5 - Link Measurement Report frame format */
 struct rrm_link_measurement_report {
 	u8 dialog_token;
 	struct tpc_report tpc;
@@ -2068,7 +2138,7 @@
 	u8 variable[0];
 } STRUCT_PACKED;
 
-/* IEEE Std 802.11-2016, 9.4.2.21 - Measurement Request element */
+/* IEEE Std 802.11-2020, 9.4.2.20 - Measurement Request element */
 struct rrm_measurement_request_element {
 	u8 eid; /* Element ID */
 	u8 len; /* Length */
@@ -2078,14 +2148,14 @@
 	u8 variable[0]; /* Measurement Request */
 } STRUCT_PACKED;
 
-/* IEEE Std 802.11-2016, Figure 9-148 - Measurement Request Mode field */
+/* IEEE Std 802.11-2020, Figure 9-180 - Measurement Request Mode field format */
 #define MEASUREMENT_REQUEST_MODE_PARALLEL BIT(0)
 #define MEASUREMENT_REQUEST_MODE_ENABLE BIT(1)
 #define MEASUREMENT_REQUEST_MODE_REQUEST BIT(2)
 #define MEASUREMENT_REQUEST_MODE_REPORT BIT(3)
 #define MEASUREMENT_REQUEST_MODE_DURATION_MANDATORY BIT(4)
 
-/* IEEE Std 802.11-2016, 9.4.2.21.7 - Beacon request */
+/* IEEE Std 802.11-2020, 9.4.2.20.7 - Beacon request */
 struct rrm_measurement_beacon_request {
 	u8 oper_class; /* Operating Class */
 	u8 channel; /* Channel Number */
@@ -2097,7 +2167,7 @@
 } STRUCT_PACKED;
 
 /*
- * IEEE Std 802.11-2016, Table 9-87 - Measurement Mode definitions for Beacon
+ * IEEE Std 802.11-2020, Table 9-103 - Measurement Mode definitions for Beacon
  * request
  */
 enum beacon_report_mode {
@@ -2106,20 +2176,19 @@
 	BEACON_REPORT_MODE_TABLE = 2,
 };
 
-/* IEEE Std 802.11-2016, Table 9-88 - Beacon Request subelement IDs */
-/* IEEE P802.11-REVmd/D2.0, Table 9-106 - Optional subelement IDs for
+/* IEEE Std 802.11-2020, Table 9-104 - Optional subelement IDs for
  * Beacon request */
 #define WLAN_BEACON_REQUEST_SUBELEM_SSID	0
 #define WLAN_BEACON_REQUEST_SUBELEM_INFO	1 /* Beacon Reporting */
 #define WLAN_BEACON_REQUEST_SUBELEM_DETAIL	2 /* Reporting Detail */
 #define WLAN_BEACON_REQUEST_SUBELEM_REQUEST	10
+#define WLAN_BEACON_REQUEST_SUBELEM_EXT_REQUEST	11
 #define WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL	51 /* AP Channel Report */
+#define WLAN_BEACON_REQUEST_SUBELEM_WIDE_BW_CS	163
 #define WLAN_BEACON_REQUEST_SUBELEM_LAST_INDICATION	164
 #define WLAN_BEACON_REQUEST_SUBELEM_VENDOR	221
 
-/*
- * IEEE Std 802.11-2016, Table 9-90 - Reporting Detail values
- */
+/* IEEE Std 802.11-2020, Table 9-106 - Reporting Detail values */
 enum beacon_report_detail {
 	/* No fixed-length fields or elements */
 	BEACON_REPORT_DETAIL_NONE = 0,
@@ -2131,7 +2200,7 @@
 	BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS = 2,
 };
 
-/* IEEE Std 802.11-2016, 9.4.2.22 - Measurement Report element */
+/* IEEE Std 802.11-2020, 9.4.2.21 - Measurement Report element */
 struct rrm_measurement_report_element {
 	u8 eid; /* Element ID */
 	u8 len; /* Length */
@@ -2141,13 +2210,13 @@
 	u8 variable[0]; /* Measurement Report */
 } STRUCT_PACKED;
 
-/* IEEE Std 802.11-2016, Figure 9-192 - Measurement Report Mode field */
+/* IEEE Std 802.11-2020, Figure 9-223 - Measurement Report Mode field */
 #define MEASUREMENT_REPORT_MODE_ACCEPT 0
 #define MEASUREMENT_REPORT_MODE_REJECT_LATE BIT(0)
 #define MEASUREMENT_REPORT_MODE_REJECT_INCAPABLE BIT(1)
 #define MEASUREMENT_REPORT_MODE_REJECT_REFUSED BIT(2)
 
-/* IEEE Std 802.11-2016, 9.4.2.22.7 - Beacon report */
+/* IEEE Std 802.11-2020, 9.4.2.21.7 - Beacon report */
 struct rrm_measurement_beacon_report {
 	u8 op_class; /* Operating Class */
 	u8 channel; /* Channel Number */
@@ -2163,23 +2232,23 @@
 	u8 variable[0]; /* Optional Subelements */
 } STRUCT_PACKED;
 
-/* IEEE Std 802.11-2016, Table 9-112 - Beacon report Subelement IDs */
-/* IEEE P802.11-REVmd/D2.0, Table 9-130 - Optional subelement IDs for
+/* IEEE Std 802.11-2020, Table 9-130 - Optional subelement IDs for
  * Beacon report */
 #define WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY	1
 #define WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY_FRAGMENT_ID	2
+#define WLAN_BEACON_REPORT_SUBELEM_WID_BW_CS	163
 #define WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION	164
 #define WLAN_BEACON_REPORT_SUBELEM_VENDOR	221
 
-/* IEEE P802.11-REVmd/D2.0, Table 9-232 - Data field format of the
- * Reported Frame Body Fragment ID subelement */
+/* IEEE Std 802.11-2020, Table 9-232 - Data field format (of the
+ * Reported Frame Body Fragment ID subelement) */
 #define REPORTED_FRAME_BODY_SUBELEM_LEN		4
 #define REPORTED_FRAME_BODY_MORE_FRAGMENTS	BIT(7)
 
-/* IEEE P802.11-REVmd/D2.0, 9.4.2.21.7 - Beacon report  */
+/* IEEE Std 802.11-2020, 9.4.2.21.7 - Beacon report  */
 #define BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN	3
 
-/* IEEE Std 802.11ad-2012 - Multi-band element */
+/* IEEE Std 802.11-2020, 9.4.2.138 - Multi-band element */
 struct multi_band_ie {
 	u8 eid; /* WLAN_EID_MULTI_BAND */
 	u8 len;
@@ -2225,7 +2294,7 @@
 #define MB_CONNECTION_CAPABILITY_TDLS ((u8) (BIT(3)))
 #define MB_CONNECTION_CAPABILITY_IBSS ((u8) (BIT(4)))
 
-/* IEEE Std 802.11ad-2014 - FST Action field */
+/* IEEE Std 802.11-2020, Table 9-479 - FST Action field values */
 enum fst_action {
 	FST_ACTION_SETUP_REQUEST = 0,
 	FST_ACTION_SETUP_RESPONSE = 1,
@@ -2235,21 +2304,23 @@
 	FST_ACTION_ON_CHANNEL_TUNNEL = 5,
 };
 
-/* IEEE Std 802.11ac-2013, Annex C - dot11PHYType */
+/* IEEE Std 802.11-2020, Annex C - dot11PHYType */
 enum phy_type {
 	PHY_TYPE_UNSPECIFIED = 0,
-	PHY_TYPE_FHSS = 1,
 	PHY_TYPE_DSSS = 2,
-	PHY_TYPE_IRBASEBAND = 3,
 	PHY_TYPE_OFDM = 4,
 	PHY_TYPE_HRDSSS = 5,
 	PHY_TYPE_ERP = 6,
 	PHY_TYPE_HT = 7,
 	PHY_TYPE_DMG = 8,
 	PHY_TYPE_VHT = 9,
+	PHY_TYPE_TVHT = 10,
+	PHY_TYPE_S1G = 11,
+	PHY_TYPE_CDMG = 12,
+	PHY_TYPE_CMMG = 13,
 };
 
-/* IEEE P802.11-REVmd/D3.0, 9.4.2.36 - Neighbor Report element */
+/* IEEE Std 802.11-2020, 9.4.2.36 - Neighbor Report element */
 /* BSSID Information Field */
 #define NEI_REP_BSSID_INFO_AP_NOT_REACH BIT(0)
 #define NEI_REP_BSSID_INFO_AP_UNKNOWN_REACH BIT(1)
@@ -2270,7 +2341,7 @@
 #define NEI_REP_BSSID_INFO_EHT BIT(21)
 
 /*
- * IEEE P802.11-REVmc/D5.0 Table 9-152 - HT/VHT Operation Information
+ * IEEE Std 802.11-2020, Table 9-175 - HT/VHT Operation Information
  * subfields.
  * Note: These definitions are not the same as other CHANWIDTH_*.
  */
@@ -2434,16 +2505,31 @@
 #define HE_OPERATION_6GHZ_OPER_INFO_LEN 5
 
 /**
- * enum he_6ghz_ap_type - Allowed Access Point types for 6 GHz Band
+ * enum he_reg_info_6ghz_ap_type - Allowed Access Point types for 6 GHz Band
  *
- * IEEE Std 802.11ax-2021, Table E-12 (Regulatory Info subfield encoding in the
- * United States)
+ * IEEE P802.11-REVme/D4.0, Table E-12 (Regulatory Info subfield encoding)
  */
-enum he_6ghz_ap_type {
-	HE_6GHZ_INDOOR_AP		= 0,
-	HE_6GHZ_STANDARD_POWER_AP	= 1,
+enum he_reg_info_6ghz_ap_type {
+	HE_REG_INFO_6GHZ_AP_TYPE_INDOOR         = 0,
+	HE_REG_INFO_6GHZ_AP_TYPE_SP		= 1,
+	HE_REG_INFO_6GHZ_AP_TYPE_VLP		= 2,
+	HE_REG_INFO_6GHZ_AP_TYPE_INDOOR_ENABLED	= 3,
+	HE_REG_INFO_6GHZ_AP_TYPE_INDOOR_SP	= 4,
+	HE_REG_INFO_6GHZ_AP_TYPE_MAX = HE_REG_INFO_6GHZ_AP_TYPE_INDOOR_SP,
 };
 
+static inline bool he_reg_is_indoor(enum he_reg_info_6ghz_ap_type type)
+{
+	return type == HE_REG_INFO_6GHZ_AP_TYPE_INDOOR ||
+		type == HE_REG_INFO_6GHZ_AP_TYPE_INDOOR_SP;
+}
+
+static inline bool he_reg_is_sp(enum he_reg_info_6ghz_ap_type type)
+{
+	return type == HE_REG_INFO_6GHZ_AP_TYPE_SP ||
+		type == HE_REG_INFO_6GHZ_AP_TYPE_INDOOR_SP;
+}
+
 /* Spatial Reuse defines */
 #define SPATIAL_REUSE_SRP_DISALLOWED		BIT(0)
 #define SPATIAL_REUSE_NON_SRG_OBSS_PD_SR_DISALLOWED	BIT(1)
@@ -2511,7 +2597,18 @@
 #define RNR_BSS_PARAM_MEMBER_CO_LOCATED_ESS         BIT(4)
 #define RNR_BSS_PARAM_UNSOLIC_PROBE_RESP_ACTIVE     BIT(5)
 #define RNR_BSS_PARAM_CO_LOCATED                    BIT(6)
-#define RNR_20_MHZ_PSD_MAX_TXPOWER                  255 /* dBm */
+/* Maximum transmit power in Y/2 dBm (-127..126); 127 indicates no maximum
+ * transmit power is specified for the corresponding 20 MHz channel. */
+#define RNR_20_MHZ_PSD_MAX_TXPOWER                  127
+
+/* IEEE P802.11be/D5.0, Figure 9-704c - MLD Parameters subfield format */
+/* B0..B7: AP MLD ID */
+/* B8..B11: Link ID */
+/* B12..B19: BSS Parameters Change Count */
+/* B20: All Updates Included */
+#define RNR_TBTT_INFO_MLD_PARAM2_ALL_UPDATE_INC 0x10
+/* B21: Disabled Link Indication */
+#define RNR_TBTT_INFO_MLD_PARAM2_LINK_DISABLED  0x20
 
 /* IEEE P802.11be/D2.3, 9.4.2.311 - EHT Operation element */
 
@@ -2725,6 +2822,17 @@
 #define EHT_PER_STA_CTRL_NSTR_BM_SIZE_MSK             0x0400
 #define EHT_PER_STA_CTRL_BSS_PARAM_CNT_PRESENT_MSK    0x0800
 
+/* IEEE P802.11be/D4.1, Figure 9-1001x - STA Control field format for the
+ * Reconfiguration Multi-Link element */
+#define EHT_PER_STA_RECONF_CTRL_LINK_ID_MSK        0x000f
+#define EHT_PER_STA_RECONF_CTRL_COMPLETE_PROFILE   0x0010
+#define EHT_PER_STA_RECONF_CTRL_MAC_ADDR           0x0020
+#define EHT_PER_STA_RECONF_CTRL_AP_REMOVAL_TIMER   0x0040
+#define EHT_PER_STA_RECONF_CTRL_OP_UPDATE_TYPE_MSK 0x0780
+#define EHT_PER_STA_RECONF_CTRL_OP_PARAMS          0x0800
+#define EHT_PER_STA_RECONF_CTRL_NSTR_BITMAP_SIZE   0x1000
+#define EHT_PER_STA_RECONF_CTRL_NSTR_INDIC_BITMAP  0x2000
+
 /* IEEE P802.11be/D2.0, 9.4.2.312.2.4 - Per-STA Profile subelement format */
 struct ieee80211_eht_per_sta_profile {
 	le16 sta_control;
@@ -2733,9 +2841,11 @@
 	u8 variable[];
 } STRUCT_PACKED;
 
-/* IEEE P802.11be/D2.0, 9.4.2.312.3 - Probe Request Multi-Link element */
+/* IEEE P802.11be/D4.0, 9.4.2.312.3 - Probe Request Multi-Link element
+ * Presence Bitmap field is B4..B15 of the Multi-Link Control field, i.e.,
+ * B0 in the presence bitmap is B4 in the control field. */
 
-#define EHT_ML_PRES_BM_PROBE_REQ_AP_MLD_ID 0x0001
+#define EHT_ML_PRES_BM_PROBE_REQ_AP_MLD_ID 0x0010
 
 struct eht_ml_probe_req_common_info {
 	u8 len;
@@ -2869,8 +2979,8 @@
 };
 
 /*
- * IEEE Std 802.11ai-2016, 9.6.8.36 FILS Discovery frame format,
- * Figure 9-687b - FILS Discovery Frame Control subfield format
+ * IEEE Std 802.11-2020, 9.6.7.36 FILS Discovery frame format,
+ * Figure 9-900 - FILS Discovery Frame Control subfield format
  */
 #define FD_FRAME_CTL_CAP_PRESENT			((u16) BIT(5))
 #define FD_FRAME_CTL_SHORT_SSID_PRESENT			((u16) BIT(6))
@@ -2883,8 +2993,8 @@
 #define FD_FRAME_CTL_MD_PRESENT				((u16) BIT(13))
 
 /*
- * IEEE Std 802.11ai-2016, 9.6.8.36 FILS Discovery frame format,
- * Figure 9-687c - FD Capability subfield format
+ * IEEE Std 802.11-2020, 9.6.7.36 FILS Discovery frame format,
+ * Figure 9-901 - FD Capability subfield format
  */
 #define FD_CAP_ESS					BIT(0)
 #define FD_CAP_PRIVACY					BIT(1)
@@ -2973,6 +3083,15 @@
 	u8 data[0];
 } STRUCT_PACKED;
 
+/* S1G Beacon Compatibility element */
+struct ieee80211_s1g_beacon_compat {
+	u8 element_id;
+	u8 length;
+	le16 compat_info;
+	le16 beacon_interval;
+	le32 tsf_completion;
+} STRUCT_PACKED;
+
 #ifdef _MSC_VER
 #pragma pack(pop)
 #endif /* _MSC_VER */
diff --git a/src/common/nan.h b/src/common/nan.h
new file mode 100644
index 0000000..19ab746
--- /dev/null
+++ b/src/common/nan.h
@@ -0,0 +1,98 @@
+/*
+ * NAN (Wi-Fi Aware) definitions
+ * 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_H
+#define NAN_H
+
+enum nan_attr_id {
+	NAN_ATTR_MASTER_INDICATION = 0x00,
+	NAN_ATTR_CLUSTER = 0x01,
+	NAN_ATTR_NAN_ATTR_SERVICE_ID_LIST = 0x02,
+	NAN_ATTR_SDA = 0x03, /* Service Descriptor attribute */
+	NAN_ATTR_CONN_CAPA = 0x04,
+	NAN_ATTR_WLAN_INFRA = 0x05,
+	NAN_ATTR_P2P_OPER = 0x06,
+	NAN_ATTR_IBSS = 0x07,
+	NAN_ATTR_MESH = 0x08,
+	NAN_ATTR_FURTHER_NAN_SD = 0x09,
+	NAN_ATTR_FURTHER_AVAIL_MAP = 0x0A,
+	NAN_ATTR_COUNTRY_CODE = 0x0B,
+	NAN_ATTR_RANGIN = 0x0C,
+	NAN_ATTR_CLUSTER_DISCOVERY = 0x0D,
+	NAN_ATTR_SDEA = 0x0E, /* Service Descriptor Extension attribute */
+	NAN_ATTR_DEVICE_CAPABILITY = 0x0F,
+	NAN_ATTR_NDP = 0x10,
+	NAN_ATTR_NAN_AVAILABILITY = 0x12,
+	NAN_ATTR_NDC = 0x13,
+	NAN_ATTR_NDL = 0x14,
+	NAN_ATTR_NDL_QOS = 0x15,
+	NAN_ATTR_UNALIGNED_SCHEDULE = 0x17,
+	NAN_ATTR_RANGING_INFO = 0x1A,
+	NAN_ATTR_RANGING_SETUP = 0x1B,
+	NAN_ATTR_FTM_RANGING_REPORT = 0x1C,
+	NAN_ATTR_ELEM_CONTAINER = 0x1D,
+	NAN_ATTR_EXT_WLAN_INFRA = 0x1E,
+	NAN_ATTR_EXT_P2P_OPER = 0x1FE,
+	NAN_ATTR_EXT_IBSS = 0x20,
+	NAN_ATTR_EXT_MESH = 0x21,
+	NAN_ATTR_CSIA = 0x22, /* Cipher Suite Info attribute */
+	NAN_ATTR_SCIA = 0x23, /* Security Context Info attribute */
+	NAN_ATTR_SHARED_KEY_DESCR = 0x24,
+	NAN_ATTR_PUBLIC_AVAILABILITY = 0x27,
+	NAN_ATTR_SUBSC_SERVICE_ID_LIST = 0x28,
+	NAN_ATTR_NDP_EXT = 0x29,
+	NAN_ATTR_DCEA = 0x2A, /* Device Capability Extension attribute */
+	NAN_ATTR_NIRA = 0x2B, /* NAN Identity Resolution attribute */
+	NAN_ATTR_BPBA = 0x2C, /* NAN Pairing Bootstrapping attribute */
+	NAN_ATTR_S3 = 0x2D,
+	NAN_ATTR_TPEA = 0x2E, /* Transmit Power Envelope attribute */
+	NAN_ATTR_VENDOR_SPECIFIC = 0xDD,
+};
+
+/* Service Descriptor attribute (SDA) */
+
+/* Service Control field */
+#define NAN_SRV_CTRL_TYPE_MASK (BIT(0) | BIT(1))
+#define NAN_SRV_CTRL_MATCHING_FILTER BIT(2)
+#define NAN_SRV_CTRL_RESP_FILTER BIT(3)
+#define NAN_SRV_CTRL_SRV_INFO BIT(4)
+#define NAN_SRV_CTRL_DISCOVERY_RANGE_LIMITED BIT(5)
+#define NAN_SRV_CTRL_BINDING_BITMAP BIT(6)
+
+enum nan_service_control_type {
+	NAN_SRV_CTRL_PUBLISH = 0,
+	NAN_SRV_CTRL_SUBSCRIBE = 1,
+	NAN_SRV_CTRL_FOLLOW_UP = 2,
+};
+
+/* Service Descriptor Extension attribute (SDEA) */
+
+/* SDEA Control field */
+#define NAN_SDEA_CTRL_FSD_REQ BIT(0)
+#define NAN_SDEA_CTRL_FSD_GAS BIT(1)
+#define NAN_SDEA_CTRL_DATA_PATH_REQ BIT(2)
+#define NAN_SDEA_CTRL_DATA_PATH_TYPE BIT(3)
+#define NAN_SDEA_CTRL_QOS_REQ BIT(5)
+#define NAN_SDEA_CTRL_SECURITY_REQ BIT(6)
+#define NAN_SDEA_CTRL_RANGING_REQ BIT(7)
+#define NAN_SDEA_CTRL_RANGE_LIMIT BIT(8)
+#define NAN_SDEA_CTRL_SRV_UPD_INDIC BIT(9)
+#define NAN_SDEA_CTRL_GTK_REQ BIT(10)
+
+enum nan_service_protocol_type {
+	NAN_SRV_PROTO_BONJOUR = 1,
+	NAN_SRV_PROTO_GENERIC = 2,
+	NAN_SRV_PROTO_CSA_MATTER = 3,
+};
+
+#define NAN_ATTR_HDR_LEN 3
+#define NAN_SERVICE_ID_LEN 6
+
+#define NAN_USD_DEFAULT_FREQ 2437
+
+#endif /* NAN_H */
diff --git a/src/common/nan_de.c b/src/common/nan_de.c
new file mode 100644
index 0000000..e1999a0
--- /dev/null
+++ b/src/common/nan_de.c
@@ -0,0 +1,1389 @@
+/*
+ * NAN Discovery Engine
+ * 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 "utils/eloop.h"
+#include "crypto/crypto.h"
+#include "crypto/sha256.h"
+#include "ieee802_11_defs.h"
+#include "nan.h"
+#include "nan_de.h"
+
+static const u8 nan_network_id[ETH_ALEN] =
+{ 0x51, 0x6f, 0x9a, 0x01, 0x00, 0x00 };
+static const u8 wildcard_bssid[ETH_ALEN] =
+{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+enum nan_de_service_type {
+	NAN_DE_PUBLISH,
+	NAN_DE_SUBSCRIBE,
+};
+
+struct nan_de_service {
+	int id;
+	enum nan_de_service_type type;
+	char *service_name;
+	u8 service_id[NAN_SERVICE_ID_LEN];
+	struct nan_publish_params publish;
+	struct nan_subscribe_params subscribe;
+	enum nan_service_protocol_type srv_proto_type;
+	struct wpabuf *ssi;
+	struct wpabuf *elems;
+	struct os_reltime time_started;
+	struct os_reltime end_time;
+	struct os_reltime last_multicast;
+	struct os_reltime first_discovered;
+	struct os_reltime last_followup;
+	bool needs_fsd;
+	unsigned int freq;
+	unsigned int default_freq;
+	int *freq_list;
+
+	/* pauseState information for Publish function */
+	struct os_reltime pause_state_end;
+	u8 sel_peer_id;
+	u8 sel_peer_addr[ETH_ALEN];
+
+	/* Publish state - channel iteration */
+	bool in_multi_chan;
+	bool first_multi_chan;
+	int multi_chan_idx; /* index to freq_list[] */
+	struct os_reltime next_publish_state;
+	struct os_reltime next_publish_chan;
+	unsigned int next_publish_duration;
+};
+
+struct nan_de {
+	u8 nmi[ETH_ALEN];
+	bool ap;
+	struct nan_callbacks cb;
+
+	struct nan_de_service *service[NAN_DE_MAX_SERVICE];
+	unsigned int num_service;
+
+	int next_handle;
+
+	unsigned int ext_listen_freq;
+	unsigned int listen_freq;
+	unsigned int tx_wait_status_freq;
+	unsigned int tx_wait_end_freq;
+};
+
+
+struct nan_de * nan_de_init(const u8 *nmi, bool ap,
+			    const struct nan_callbacks *cb)
+{
+	struct nan_de *de;
+
+	de = os_zalloc(sizeof(*de));
+	if (!de)
+		return NULL;
+
+	os_memcpy(de->nmi, nmi, ETH_ALEN);
+	de->ap = ap;
+	os_memcpy(&de->cb, cb, sizeof(*cb));
+
+	return de;
+}
+
+
+static void nan_de_service_free(struct nan_de_service *srv)
+{
+	os_free(srv->service_name);
+	wpabuf_free(srv->ssi);
+	wpabuf_free(srv->elems);
+	os_free(srv->freq_list);
+	os_free(srv);
+}
+
+
+static void nan_de_service_deinit(struct nan_de *de, struct nan_de_service *srv,
+				  enum nan_de_reason reason)
+{
+	if (!srv)
+		return;
+	if (srv->type == NAN_DE_PUBLISH && de->cb.publish_terminated)
+		de->cb.publish_terminated(de->cb.ctx, srv->id, reason);
+	if (srv->type == NAN_DE_SUBSCRIBE && de->cb.subscribe_terminated)
+		de->cb.subscribe_terminated(de->cb.ctx, srv->id, reason);
+	nan_de_service_free(srv);
+}
+
+
+static void nan_de_clear_pending(struct nan_de *de)
+{
+	de->listen_freq = 0;
+	de->tx_wait_status_freq = 0;
+	de->tx_wait_end_freq = 0;
+}
+
+
+void nan_de_flush(struct nan_de *de)
+{
+	unsigned int i;
+
+	if (!de)
+		return;
+
+	for (i = 0; i < NAN_DE_MAX_SERVICE; i++) {
+		nan_de_service_deinit(de, de->service[i],
+				      NAN_DE_REASON_USER_REQUEST);
+		de->service[i] = NULL;
+	}
+
+	de->num_service = 0;
+	nan_de_clear_pending(de);
+}
+
+
+static void nan_de_pause_state(struct nan_de_service *srv, const u8 *peer_addr,
+			       u8 peer_id)
+{
+	wpa_printf(MSG_DEBUG, "NAN: Start pauseState");
+	os_get_reltime(&srv->pause_state_end);
+	srv->pause_state_end.sec += 60;
+	os_memcpy(srv->sel_peer_addr, peer_addr, ETH_ALEN);
+	srv->sel_peer_id = peer_id;
+}
+
+
+static void nan_de_unpause_state(struct nan_de_service *srv)
+{
+	wpa_printf(MSG_DEBUG, "NAN: Stop pauseState");
+	srv->pause_state_end.sec = 0;
+	srv->pause_state_end.usec = 0;
+	os_memset(srv->sel_peer_addr, 0, ETH_ALEN);
+	srv->sel_peer_id = 0;
+}
+
+
+static struct wpabuf * nan_de_alloc_sdf(size_t len)
+{
+	struct wpabuf *buf;
+
+	buf = wpabuf_alloc(2 + 4 + len);
+	if (buf) {
+		wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
+		wpabuf_put_u8(buf, WLAN_PA_VENDOR_SPECIFIC);
+		wpabuf_put_be32(buf, NAN_SDF_VENDOR_TYPE);
+	}
+
+	return buf;
+}
+
+
+static int nan_de_tx(struct nan_de *de, unsigned int freq,
+		     unsigned int wait_time,
+		     const u8 *dst, const u8 *src, const u8 *bssid,
+		     const struct wpabuf *buf)
+{
+	int res;
+
+	if (!de->cb.tx)
+		return -1;
+
+	res = de->cb.tx(de->cb.ctx, freq, wait_time, dst, src, bssid, buf);
+	if (res < 0)
+		return res;
+
+	de->tx_wait_status_freq = freq;
+	de->tx_wait_end_freq = wait_time ? freq : 0;
+
+	return res;
+}
+
+
+static void nan_de_tx_sdf(struct nan_de *de, struct nan_de_service *srv,
+			  unsigned int wait_time,
+			  enum nan_service_control_type type,
+			  const u8 *dst, u8 req_instance_id,
+			  const struct wpabuf *ssi)
+{
+	struct wpabuf *buf;
+	size_t len = 0, sda_len, sdea_len;
+	u8 ctrl = type;
+	u16 sdea_ctrl = 0;
+
+	/* Service Descriptor attribute */
+	sda_len = NAN_SERVICE_ID_LEN + 1 + 1 + 1;
+	len += NAN_ATTR_HDR_LEN + sda_len;
+
+	/* Service Descriptor Extension attribute */
+	sdea_len = 1 + 2;
+	if (ssi)
+		sdea_len += 2 + 4 + wpabuf_len(ssi);
+	len += NAN_ATTR_HDR_LEN + sdea_len;
+
+	/* Element Container attribute */
+	if (srv->elems)
+		len += NAN_ATTR_HDR_LEN + 1 + wpabuf_len(srv->elems);
+
+	buf = nan_de_alloc_sdf(len);
+	if (!buf)
+		return;
+
+	/* Service Descriptor attribute */
+	wpabuf_put_u8(buf, NAN_ATTR_SDA);
+	wpabuf_put_le16(buf, sda_len);
+	wpabuf_put_data(buf, srv->service_id, NAN_SERVICE_ID_LEN);
+	wpabuf_put_u8(buf, srv->id); /* Instance ID */
+	wpabuf_put_u8(buf, req_instance_id); /* Requestor Instance ID */
+	wpabuf_put_u8(buf, ctrl);
+
+	/* Service Descriptor Extension attribute */
+	if (srv->type == NAN_DE_PUBLISH || ssi) {
+		wpabuf_put_u8(buf, NAN_ATTR_SDEA);
+		wpabuf_put_le16(buf, sdea_len);
+		wpabuf_put_u8(buf, srv->id); /* Instance ID */
+		if (srv->type == NAN_DE_PUBLISH) {
+			if (srv->publish.fsd)
+				sdea_ctrl |= NAN_SDEA_CTRL_FSD_REQ;
+			if (srv->publish.fsd_gas)
+				sdea_ctrl |= NAN_SDEA_CTRL_FSD_GAS;
+		}
+		wpabuf_put_le16(buf, sdea_ctrl);
+		if (ssi) {
+			wpabuf_put_le16(buf, 4 + wpabuf_len(ssi));
+			wpabuf_put_be24(buf, OUI_WFA);
+			wpabuf_put_u8(buf, srv->srv_proto_type);
+			wpabuf_put_buf(buf, ssi);
+		}
+	}
+
+	/* Element Container attribute */
+	if (srv->elems) {
+		wpabuf_put_u8(buf, NAN_ATTR_ELEM_CONTAINER);
+		wpabuf_put_le16(buf, 1 + wpabuf_len(srv->elems));
+		wpabuf_put_u8(buf, 0); /* Map ID */
+		wpabuf_put_buf(buf, srv->elems);
+	}
+
+	/* Wi-Fi Aware specification v4.0 uses NAN Cluster ID as A3 for USD,
+	 * but there is no synchronization in USD as as such, no NAN Cluster
+	 * either. Use Wildcard BSSID instead. */
+	nan_de_tx(de, srv->freq, wait_time, dst, de->nmi, wildcard_bssid, buf);
+	wpabuf_free(buf);
+}
+
+
+static int nan_de_time_to_next_chan_change(struct nan_de_service *srv)
+{
+	struct os_reltime tmp, diff, now;
+
+	if (os_reltime_before(&srv->next_publish_state,
+			      &srv->next_publish_chan))
+		tmp = srv->next_publish_state;
+	else if (srv->in_multi_chan)
+		tmp = srv->next_publish_chan;
+	else
+		tmp = srv->next_publish_state;
+
+	os_get_reltime(&now);
+	os_reltime_sub(&tmp, &now, &diff);
+	return os_reltime_in_ms(&diff);
+}
+
+
+static void nan_de_set_publish_times(struct nan_de_service *srv)
+{
+	os_get_reltime(&srv->next_publish_state);
+	srv->next_publish_chan = srv->next_publish_state;
+	/* Swap single/multi channel state in N * 100 TU */
+	os_reltime_add_ms(&srv->next_publish_state,
+			  srv->next_publish_duration * 1024 / 1000);
+
+	/* Swap channel in multi channel state after 150 ms */
+	os_reltime_add_ms(&srv->next_publish_chan, 150);
+}
+
+
+static void nan_de_check_chan_change(struct nan_de_service *srv)
+{
+	if (srv->next_publish_duration) {
+		/* Update end times for the first operation of the publish
+		 * iteration */
+		nan_de_set_publish_times(srv);
+		srv->next_publish_duration = 0;
+	} else if (srv->in_multi_chan) {
+		if (!os_reltime_initialized(&srv->pause_state_end)) {
+			srv->multi_chan_idx++;
+			if (srv->freq_list[srv->multi_chan_idx] == 0)
+				srv->multi_chan_idx = 0;
+			srv->freq = srv->freq_list[srv->multi_chan_idx];
+			wpa_printf(MSG_DEBUG,
+				   "NAN: Publish multi-channel change to %u MHz",
+				   srv->freq);
+		}
+		os_get_reltime(&srv->next_publish_chan);
+		os_reltime_add_ms(&srv->next_publish_chan, 150);
+	}
+}
+
+
+static void nan_de_tx_multicast(struct nan_de *de, struct nan_de_service *srv,
+				u8 req_instance_id)
+{
+	enum nan_service_control_type type;
+	unsigned int wait_time = 100;
+
+	if (srv->type == NAN_DE_PUBLISH) {
+		int ms;
+
+		type = NAN_SRV_CTRL_PUBLISH;
+
+		nan_de_check_chan_change(srv);
+		ms = nan_de_time_to_next_chan_change(srv);
+		if (ms < 100)
+			ms = 100;
+		wait_time = ms;
+	} else if (srv->type == NAN_DE_SUBSCRIBE) {
+		type = NAN_SRV_CTRL_SUBSCRIBE;
+	} else {
+		return;
+	}
+
+	nan_de_tx_sdf(de, srv, wait_time, type, nan_network_id,
+		      req_instance_id, srv->ssi);
+	os_get_reltime(&srv->last_multicast);
+}
+
+
+static void nan_de_add_srv(struct nan_de *de, struct nan_de_service *srv)
+{
+	int ttl;
+
+	os_get_reltime(&srv->time_started);
+	ttl = srv->type == NAN_DE_PUBLISH ? srv->publish.ttl :
+		srv->subscribe.ttl;
+	if (ttl) {
+		srv->end_time = srv->time_started;
+		srv->end_time.sec += ttl;
+	}
+
+	de->service[srv->id - 1] = srv;
+	de->num_service++;
+}
+
+
+static void nan_de_del_srv(struct nan_de *de, struct nan_de_service *srv,
+			   enum nan_de_reason reason)
+{
+	de->service[srv->id - 1] = NULL;
+	nan_de_service_deinit(de, srv, reason);
+	de->num_service--;
+	if (de->num_service == 0)
+		nan_de_clear_pending(de);
+}
+
+
+static bool nan_de_srv_expired(struct nan_de_service *srv,
+			       struct os_reltime *now)
+{
+	if (os_reltime_initialized(&srv->end_time))
+		return os_reltime_before(&srv->end_time, now);
+
+	if (srv->type == NAN_DE_PUBLISH) {
+		/* Time out after one transmission (and wait for FSD) */
+		if (!os_reltime_initialized(&srv->last_multicast))
+			return false;
+		if (!srv->publish.fsd)
+			return true;
+		if (os_reltime_initialized(&srv->last_followup) &&
+		    !os_reltime_expired(now, &srv->last_followup, 1))
+			return false;
+		if (os_reltime_expired(now, &srv->last_multicast, 1))
+			return true;
+	}
+
+	if (srv->type == NAN_DE_SUBSCRIBE) {
+		/* Time out after first DiscoveryResult event (and wait for
+		 * FSD) */
+		if (!os_reltime_initialized(&srv->first_discovered))
+			return false;
+		if (!srv->needs_fsd)
+			return true;
+		if (os_reltime_initialized(&srv->last_followup) &&
+		    !os_reltime_expired(now, &srv->last_followup, 1))
+			return false;
+		if (os_reltime_expired(now, &srv->first_discovered, 1))
+			return true;
+	}
+
+	return false;
+}
+
+
+static int nan_de_next_multicast(struct nan_de *de, struct nan_de_service *srv,
+				 struct os_reltime *now)
+{
+	unsigned int period;
+	struct os_reltime next, diff;
+
+	if (srv->type == NAN_DE_PUBLISH && !srv->publish.unsolicited)
+		return -1;
+	if (srv->type == NAN_DE_SUBSCRIBE && !srv->subscribe.active)
+		return -1;
+
+	if (!os_reltime_initialized(&srv->last_multicast))
+		return 0;
+
+	if (srv->type == NAN_DE_PUBLISH && srv->publish.ttl == 0)
+		return -1;
+
+	if (srv->type == NAN_DE_PUBLISH &&
+	    os_reltime_initialized(&srv->pause_state_end))
+		return -1;
+
+	period = srv->type == NAN_DE_PUBLISH ?
+		srv->publish.announcement_period :
+		srv->subscribe.query_period;
+	if (period == 0)
+		period = 100;
+	next = srv->last_multicast;
+	os_reltime_add_ms(&next, period);
+
+	if (srv->type == NAN_DE_PUBLISH) {
+		if (!de->tx_wait_end_freq && srv->publish.unsolicited &&
+		    os_reltime_before(&next, now))
+			return 0;
+		next = srv->next_publish_state;
+	}
+
+	if (os_reltime_before(&next, now))
+		return 0;
+
+	os_reltime_sub(&next, now, &diff);
+	return os_reltime_in_ms(&diff);
+}
+
+
+static int nan_de_srv_time_to_next(struct nan_de *de,
+				   struct nan_de_service *srv,
+				   struct os_reltime *now)
+{
+	struct os_reltime diff;
+	int next = -1, tmp;
+
+	if (os_reltime_initialized(&srv->end_time)) {
+		os_reltime_sub(&srv->end_time, now, &diff);
+		tmp = os_reltime_in_ms(&diff);
+		if (next == -1 || tmp < next)
+			next = tmp;
+	}
+
+	tmp = nan_de_next_multicast(de, srv, now);
+	if (tmp >= 0 && (next == -1 || tmp < next))
+		next = tmp;
+
+	if (srv->type == NAN_DE_PUBLISH &&
+	    os_reltime_initialized(&srv->last_multicast)) {
+		/* Time out after one transmission (and wait for FSD) */
+		tmp = srv->publish.fsd ? 1000 : 100;
+		if (next == -1 || tmp < next)
+			next = tmp;
+	}
+
+	if (srv->type == NAN_DE_SUBSCRIBE &&
+	    os_reltime_initialized(&srv->first_discovered)) {
+		/* Time out after first DiscoveryResult event (and wait for
+		 * FSD) */
+		tmp = srv->needs_fsd ? 1000 : 100;
+		if (next == -1 || tmp < next)
+			next = tmp;
+	}
+
+	if (os_reltime_initialized(&srv->next_publish_state)) {
+		os_reltime_sub(&srv->next_publish_state, now, &diff);
+		if (diff.sec < 0 || (diff.sec == 0 && diff.usec < 0))
+			tmp = 0;
+		else
+			tmp = os_reltime_in_ms(&diff);
+		if (next == -1 || tmp < next)
+			next = tmp;
+	}
+
+	return next;
+}
+
+
+static void nan_de_start_new_publish_state(struct nan_de_service *srv,
+					   bool force_single)
+{
+	unsigned int n;
+
+	if (force_single || !srv->freq_list || srv->freq_list[0] == 0)
+		srv->in_multi_chan = false;
+	else
+		srv->in_multi_chan = !srv->in_multi_chan;
+
+	/* Use hardcoded Nmin=5 and Nmax=10 and pick a random N from that range.
+	 * Use same values for M. */
+	n = 5 + os_random() % 5;
+	srv->next_publish_duration = n * 100;
+
+	nan_de_set_publish_times(srv);
+
+	if (os_reltime_initialized(&srv->pause_state_end))
+		return;
+
+	if (srv->in_multi_chan && srv->freq_list && srv->freq_list[0]) {
+		if (!srv->first_multi_chan)
+			srv->multi_chan_idx++;
+		if (srv->freq_list[srv->multi_chan_idx] == 0)
+			srv->multi_chan_idx = 0;
+		srv->first_multi_chan = false;
+		srv->freq = srv->freq_list[srv->multi_chan_idx];
+	} else {
+		srv->freq = srv->default_freq;
+	}
+
+	wpa_printf(MSG_DEBUG,
+		   "NAN: Publish in %s channel state for %u TU; starting with %u MHz",
+		   srv->in_multi_chan ? "multi" : "single", n * 100, srv->freq);
+}
+
+
+static void nan_de_timer(void *eloop_ctx, void *timeout_ctx)
+{
+	struct nan_de *de = eloop_ctx;
+	unsigned int i;
+	int next = -1;
+	bool started = false;
+	struct os_reltime now;
+
+	os_get_reltime(&now);
+
+	for (i = 0; i < NAN_DE_MAX_SERVICE; i++) {
+		struct nan_de_service *srv = de->service[i];
+		int srv_next;
+
+		if (!srv)
+			continue;
+
+		if (nan_de_srv_expired(srv, &now)) {
+			wpa_printf(MSG_DEBUG, "NAN: Service id %d expired",
+				   srv->id);
+			nan_de_del_srv(de, srv, NAN_DE_REASON_TIMEOUT);
+			continue;
+		}
+
+		if (os_reltime_initialized(&srv->next_publish_state) &&
+		    os_reltime_before(&srv->next_publish_state, &now))
+			nan_de_start_new_publish_state(srv, false);
+
+		if (srv->type == NAN_DE_PUBLISH &&
+		    os_reltime_initialized(&srv->pause_state_end) &&
+		    (os_reltime_before(&srv->pause_state_end, &now) ||
+		     (srv->publish.fsd &&
+		      os_reltime_initialized(&srv->last_followup) &&
+		      os_reltime_expired(&now, &srv->last_followup, 1))))
+			nan_de_unpause_state(srv);
+
+		srv_next = nan_de_srv_time_to_next(de, srv, &now);
+		if (srv_next >= 0 && (next == -1 || srv_next < next))
+			next = srv_next;
+
+		if (srv_next == 0 && !started &&
+		    de->listen_freq == 0 && de->ext_listen_freq == 0 &&
+		    de->tx_wait_end_freq == 0 &&
+		    nan_de_next_multicast(de, srv, &now) == 0) {
+			started = true;
+			nan_de_tx_multicast(de, srv, 0);
+		}
+
+		if (!started && de->cb.listen &&
+		    de->listen_freq == 0 && de->ext_listen_freq == 0 &&
+		    de->tx_wait_end_freq == 0 &&
+		    ((srv->type == NAN_DE_PUBLISH &&
+		      !srv->publish.unsolicited && srv->publish.solicited) ||
+		     (srv->type == NAN_DE_SUBSCRIBE &&
+		      !srv->subscribe.active))) {
+			int duration = 1000;
+
+			if (srv->type == NAN_DE_PUBLISH) {
+				nan_de_check_chan_change(srv);
+				duration = nan_de_time_to_next_chan_change(srv);
+				if (duration < 150)
+					duration = 150;
+			}
+
+			started = true;
+			if (de->cb.listen(de->cb.ctx, srv->freq, duration) == 0)
+				de->listen_freq = srv->freq;
+		}
+
+	}
+
+	if (next < 0)
+		return;
+
+	if (next == 0)
+		next = 1;
+	wpa_printf(MSG_DEBUG, "NAN: Next timer in %u ms", next);
+	eloop_register_timeout(next / 1000, (next % 1000) * 1000, nan_de_timer,
+			       de, NULL);
+}
+
+
+static void nan_de_run_timer(struct nan_de *de)
+{
+	eloop_cancel_timeout(nan_de_timer, de, NULL);
+	eloop_register_timeout(0, 0, nan_de_timer, de, NULL);
+}
+
+
+void nan_de_deinit(struct nan_de *de)
+{
+	eloop_cancel_timeout(nan_de_timer, de, NULL);
+	nan_de_flush(de);
+	os_free(de);
+}
+
+
+void nan_de_listen_started(struct nan_de *de, unsigned int freq,
+			   unsigned int duration)
+{
+	if (freq != de->listen_freq)
+		de->ext_listen_freq = freq;
+}
+
+
+void nan_de_listen_ended(struct nan_de *de, unsigned int freq)
+{
+	if (freq == de->ext_listen_freq)
+		de->ext_listen_freq = 0;
+
+	if (freq == de->listen_freq) {
+		de->listen_freq = 0;
+		nan_de_run_timer(de);
+	}
+}
+
+
+void nan_de_tx_status(struct nan_de *de, unsigned int freq, const u8 *dst)
+{
+	if (freq == de->tx_wait_status_freq)
+		de->tx_wait_status_freq = 0;
+}
+
+
+void nan_de_tx_wait_ended(struct nan_de *de)
+{
+	de->tx_wait_end_freq = 0;
+	nan_de_run_timer(de);
+}
+
+
+static const u8 *
+nan_de_get_attr(const u8 *buf, size_t len, enum nan_attr_id id,
+		unsigned int skip)
+{
+	const u8 *pos = buf, *end = buf + len;
+
+	while (end - pos >= NAN_ATTR_HDR_LEN) {
+		const u8 *attr = pos;
+		u8 attr_id;
+		u16 attr_len;
+
+		attr_id = *pos++;
+		attr_len = WPA_GET_LE16(pos);
+		pos += 2;
+		if (attr_len > end - pos) {
+			wpa_printf(MSG_DEBUG,
+				   "NAN: Truncated attribute %u (len %u; left %zu)",
+				   attr_id, attr_len, end - pos);
+			break;
+		}
+
+		if (attr_id == id) {
+			if (skip == 0)
+				return attr;
+			skip--;
+		}
+
+		pos += attr_len;
+	}
+
+	return NULL;
+}
+
+
+static void nan_de_get_sdea(const u8 *buf, size_t len, u8 instance_id,
+			    u16 *sdea_control,
+			    enum nan_service_protocol_type *srv_proto_type,
+			    const u8 **ssi, size_t *ssi_len)
+{
+	unsigned int skip;
+	const u8 *sdea, *end;
+	u16 sdea_len;
+
+	for (skip = 0; ; skip++) {
+		sdea = nan_de_get_attr(buf, len, NAN_ATTR_SDEA, skip);
+		if (!sdea)
+			break;
+
+		sdea++;
+		sdea_len = WPA_GET_LE16(sdea);
+		sdea += 2;
+		if (sdea_len < 1 + 2)
+			continue;
+		end = sdea + sdea_len;
+
+		if (instance_id != *sdea++)
+			continue; /* Mismatching Instance ID */
+
+		*sdea_control = WPA_GET_LE16(sdea);
+		sdea += 2;
+
+		if (*sdea_control & NAN_SDEA_CTRL_RANGE_LIMIT) {
+			if (end - sdea < 4)
+				continue;
+			sdea += 4;
+		}
+
+		if (*sdea_control & NAN_SDEA_CTRL_SRV_UPD_INDIC) {
+			if (end - sdea < 1)
+				continue;
+			sdea++;
+		}
+
+		if (end - sdea >= 2) {
+			u16 srv_info_len;
+
+			srv_info_len = WPA_GET_LE16(sdea);
+			sdea += 2;
+
+			if (srv_info_len > end - sdea)
+				continue;
+
+			if (srv_info_len >= 4 &&
+			    WPA_GET_BE24(sdea) == OUI_WFA) {
+				*srv_proto_type = sdea[3];
+				*ssi = sdea + 4;
+				*ssi_len = srv_info_len - 4;
+			}
+		}
+	}
+}
+
+
+static void nan_de_rx_publish(struct nan_de *de, struct nan_de_service *srv,
+			      const u8 *peer_addr, u8 instance_id,
+			      u8 req_instance_id, u16 sdea_control,
+			      enum nan_service_protocol_type srv_proto_type,
+			      const u8 *ssi, size_t ssi_len)
+{
+	/* Subscribe function processing of a receive Publish message */
+	if (!os_reltime_initialized(&srv->first_discovered)) {
+		os_get_reltime(&srv->first_discovered);
+		srv->needs_fsd = sdea_control & NAN_SDEA_CTRL_FSD_REQ;
+		nan_de_run_timer(de);
+	}
+
+	if (srv->subscribe.active && req_instance_id == 0) {
+		/* Active subscriber replies with a Subscribe message if it
+		 * received a matching unsolicited Publish message. */
+		nan_de_tx_multicast(de, srv, instance_id);
+	}
+
+	if (!srv->subscribe.active && req_instance_id == 0) {
+		/* Passive subscriber replies with a Follow-up message without
+		 * Service Specific Info field if it received a matching
+		 * unsolicited Publish message. */
+		nan_de_transmit(de, srv->id, NULL, NULL, peer_addr,
+				instance_id);
+	}
+
+	if (de->cb.discovery_result)
+		de->cb.discovery_result(
+			de->cb.ctx, srv->id, srv_proto_type,
+			ssi, ssi_len, instance_id,
+			peer_addr,
+			sdea_control & NAN_SDEA_CTRL_FSD_REQ,
+			sdea_control & NAN_SDEA_CTRL_FSD_GAS);
+}
+
+
+static bool nan_de_filter_match(struct nan_de_service *srv,
+				const u8 *matching_filter,
+				size_t matching_filter_len)
+{
+	const u8 *pos, *end;
+
+	/* Since we do not currently support matching_filter_rx values for the
+	 * local Publish function, any matching filter with at least one
+	 * <length,value> pair with length larger than zero implies a mismatch.
+	 */
+
+	if (!matching_filter)
+		return true;
+
+	pos = matching_filter;
+	end = matching_filter + matching_filter_len;
+
+	while (pos < end) {
+		u8 len;
+
+		len = *pos++;
+		if (len > end - pos)
+			break;
+		if (len) {
+			/* A non-empty Matching Filter entry: no match since
+			 * there is no local matching_filter_rx. */
+			return false;
+		}
+	}
+
+	return true;
+}
+
+
+static void nan_de_rx_subscribe(struct nan_de *de, struct nan_de_service *srv,
+				const u8 *peer_addr, u8 instance_id,
+				const u8 *matching_filter,
+				size_t matching_filter_len,
+				enum nan_service_protocol_type srv_proto_type,
+				const u8 *ssi, size_t ssi_len)
+{
+	struct wpabuf *buf;
+	size_t len = 0, sda_len, sdea_len;
+	u8 ctrl = 0;
+	u16 sdea_ctrl = 0;
+
+	/* Publish function processing of a receive Subscribe message */
+
+	if (!nan_de_filter_match(srv, matching_filter, matching_filter_len))
+		return;
+
+	if (!srv->publish.solicited)
+		return;
+
+	if (os_reltime_initialized(&srv->pause_state_end) &&
+	    (!ether_addr_equal(peer_addr, srv->sel_peer_addr) ||
+	     instance_id != srv->sel_peer_id)) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: In pauseState - ignore Subscribe message from another subscriber");
+		return;
+	}
+
+	/* Reply with a solicited Publish message */
+	/* Service Descriptor attribute */
+	sda_len = NAN_SERVICE_ID_LEN + 1 + 1 + 1;
+	len += NAN_ATTR_HDR_LEN + sda_len;
+
+	/* Service Descriptor Extension attribute */
+	sdea_len = 1 + 2;
+	if (srv->ssi)
+		sdea_len += 2 + 4 + wpabuf_len(srv->ssi);
+	len += NAN_ATTR_HDR_LEN + sdea_len;
+
+	/* Element Container attribute */
+	if (srv->elems)
+		len += NAN_ATTR_HDR_LEN + 1 + wpabuf_len(srv->elems);
+
+	buf = nan_de_alloc_sdf(len);
+	if (!buf)
+		return;
+
+	/* Service Descriptor attribute */
+	wpabuf_put_u8(buf, NAN_ATTR_SDA);
+	wpabuf_put_le16(buf, sda_len);
+	wpabuf_put_data(buf, srv->service_id, NAN_SERVICE_ID_LEN);
+	wpabuf_put_u8(buf, srv->id); /* Instance ID */
+	wpabuf_put_u8(buf, instance_id); /* Requestor Instance ID */
+	ctrl |= NAN_SRV_CTRL_PUBLISH;
+	wpabuf_put_u8(buf, ctrl);
+
+	/* Service Descriptor Extension attribute */
+	if (srv->type == NAN_DE_PUBLISH || srv->ssi) {
+		wpabuf_put_u8(buf, NAN_ATTR_SDEA);
+		wpabuf_put_le16(buf, sdea_len);
+		wpabuf_put_u8(buf, srv->id); /* Instance ID */
+		if (srv->type == NAN_DE_PUBLISH) {
+			if (srv->publish.fsd)
+				sdea_ctrl |= NAN_SDEA_CTRL_FSD_REQ;
+			if (srv->publish.fsd_gas)
+				sdea_ctrl |= NAN_SDEA_CTRL_FSD_GAS;
+		}
+		wpabuf_put_le16(buf, sdea_ctrl);
+		if (srv->ssi) {
+			wpabuf_put_le16(buf, 4 + wpabuf_len(srv->ssi));
+			wpabuf_put_be24(buf, OUI_WFA);
+			wpabuf_put_u8(buf, srv->srv_proto_type);
+			wpabuf_put_buf(buf, srv->ssi);
+		}
+	}
+
+	/* Element Container attribute */
+	if (srv->elems) {
+		wpabuf_put_u8(buf, NAN_ATTR_ELEM_CONTAINER);
+		wpabuf_put_le16(buf, 1 + wpabuf_len(srv->elems));
+		wpabuf_put_u8(buf, 0); /* Map ID */
+		wpabuf_put_buf(buf, srv->elems);
+	}
+
+	/* Wi-Fi Aware specification v4.0 uses NAN Cluster ID as A3 for USD,
+	 * but there is no synchronization in USD as as such, no NAN Cluster
+	 * either. Use Wildcard BSSID instead. */
+	nan_de_tx(de, srv->freq, 100,
+		  srv->publish.solicited_multicast ? nan_network_id : peer_addr,
+		  de->nmi, wildcard_bssid, buf);
+	wpabuf_free(buf);
+
+	nan_de_pause_state(srv, peer_addr, instance_id);
+
+	if (!srv->publish.disable_events && de->cb.replied)
+		de->cb.replied(de->cb.ctx, srv->id, peer_addr, instance_id,
+			       srv_proto_type, ssi, ssi_len);
+}
+
+
+static void nan_de_rx_follow_up(struct nan_de *de, struct nan_de_service *srv,
+				const u8 *peer_addr, u8 instance_id,
+				const u8 *ssi, size_t ssi_len)
+{
+	/* Follow-up function processing of a receive Follow-up message for a
+	 * Subscribe or Publish instance */
+
+	if (srv->type == NAN_DE_PUBLISH &&
+	    os_reltime_initialized(&srv->pause_state_end) &&
+	    (!ether_addr_equal(peer_addr, srv->sel_peer_addr) ||
+	     instance_id != srv->sel_peer_id ||
+	     !ssi)) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: In pauseState - ignore Follow-up message from another subscriber or without ssi");
+		return;
+	}
+
+	os_get_reltime(&srv->last_followup);
+
+	if (srv->type == NAN_DE_PUBLISH && !ssi)
+		nan_de_pause_state(srv, peer_addr, instance_id);
+
+	if (de->cb.receive)
+		de->cb.receive(de->cb.ctx, srv->id, instance_id, ssi, ssi_len,
+			       peer_addr);
+}
+
+
+static void nan_de_rx_sda(struct nan_de *de, const u8 *peer_addr,
+			  unsigned int freq, const u8 *buf, size_t len,
+			  const u8 *sda, size_t sda_len)
+{
+	const u8 *service_id;
+	u8 instance_id, req_instance_id, ctrl;
+	u16 sdea_control = 0;
+	unsigned int i;
+	enum nan_service_control_type type = 0;
+	enum nan_service_protocol_type srv_proto_type = 0;
+	const u8 *ssi = NULL;
+	size_t ssi_len = 0;
+	bool first = true;
+	const u8 *end;
+	const u8 *matching_filter = NULL;
+	size_t matching_filter_len = 0;
+
+	if (sda_len < NAN_SERVICE_ID_LEN + 1 + 1 + 1)
+		return;
+	end = sda + sda_len;
+
+	service_id = sda;
+	sda += NAN_SERVICE_ID_LEN;
+	instance_id = *sda++;
+	req_instance_id = *sda++;
+	ctrl = *sda;
+	type = ctrl & NAN_SRV_CTRL_TYPE_MASK;
+	wpa_printf(MSG_DEBUG,
+		   "NAN: SDA - Service ID %02x%02x%02x%02x%02x%02x Instance ID %u Requestor Instance ID %u Service Control 0x%x (Service Control Type %u)",
+		   MAC2STR(service_id), instance_id, req_instance_id,
+		   ctrl, type);
+	if (type != NAN_SRV_CTRL_PUBLISH &&
+	    type != NAN_SRV_CTRL_SUBSCRIBE &&
+	    type != NAN_SRV_CTRL_FOLLOW_UP) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Discard SDF with unknown Service Control Type %u",
+			   type);
+		return;
+	}
+
+	if (ctrl & NAN_SRV_CTRL_BINDING_BITMAP) {
+		if (end - sda < 2)
+			return;
+		sda += 2;
+	}
+
+	if (ctrl & NAN_SRV_CTRL_MATCHING_FILTER) {
+		u8 flen;
+
+		if (end - sda < 1)
+			return;
+		flen = *sda++;
+		if (end - sda < flen)
+			return;
+		matching_filter = sda;
+		matching_filter_len = flen;
+		sda += flen;
+	}
+
+	if (ctrl & NAN_SRV_CTRL_RESP_FILTER) {
+		u8 flen;
+
+		if (end - sda < 1)
+			return;
+		flen = *sda++;
+		if (end - sda < flen)
+			return;
+		sda += flen;
+	}
+
+	if (ctrl & NAN_SRV_CTRL_SRV_INFO) {
+		u8 flen;
+
+		if (end - sda < 1)
+			return;
+		flen = *sda++;
+		if (end - sda < flen)
+			return;
+		if (flen >= 4 && WPA_GET_BE24(sda) == OUI_WFA) {
+			srv_proto_type = sda[3];
+			ssi = sda + 4;
+			ssi_len = flen - 4;
+			wpa_printf(MSG_DEBUG, "NAN: Service Protocol Type %d",
+				   srv_proto_type);
+			wpa_hexdump(MSG_MSGDUMP, "NAN: ssi", ssi, ssi_len);
+		}
+		sda += flen;
+	}
+
+	for (i = 0; i < NAN_DE_MAX_SERVICE; i++) {
+		struct nan_de_service *srv = de->service[i];
+
+		if (!srv)
+			continue;
+		if (os_memcmp(srv->service_id, service_id,
+			      NAN_SERVICE_ID_LEN) != 0)
+			continue;
+		if (type == NAN_SRV_CTRL_PUBLISH) {
+			if (srv->type == NAN_DE_PUBLISH)
+				continue;
+			if (req_instance_id && srv->id != req_instance_id)
+				continue;
+		}
+		if (type == NAN_SRV_CTRL_SUBSCRIBE &&
+		    srv->type == NAN_DE_SUBSCRIBE)
+			continue;
+		wpa_printf(MSG_DEBUG, "NAN: Received SDF matches service ID %u",
+			   i + 1);
+
+		if (first) {
+			first = false;
+			nan_de_get_sdea(buf, len, instance_id, &sdea_control,
+					&srv_proto_type, &ssi, &ssi_len);
+
+			if (ssi) {
+				wpa_printf(MSG_DEBUG,
+					   "NAN: Service Protocol Type %d",
+					   srv_proto_type);
+				wpa_hexdump(MSG_MSGDUMP, "NAN: ssi",
+					    ssi, ssi_len);
+			}
+		}
+
+		switch (type) {
+		case NAN_SRV_CTRL_PUBLISH:
+			nan_de_rx_publish(de, srv, peer_addr, instance_id,
+					  req_instance_id,
+					  sdea_control, srv_proto_type,
+					  ssi, ssi_len);
+			break;
+		case NAN_SRV_CTRL_SUBSCRIBE:
+			nan_de_rx_subscribe(de, srv, peer_addr, instance_id,
+					    matching_filter,
+					    matching_filter_len,
+					    srv_proto_type,
+					    ssi, ssi_len);
+			break;
+		case NAN_SRV_CTRL_FOLLOW_UP:
+			nan_de_rx_follow_up(de, srv, peer_addr, instance_id,
+					    ssi, ssi_len);
+			break;
+		}
+	}
+}
+
+
+void nan_de_rx_sdf(struct nan_de *de, const u8 *peer_addr, unsigned int freq,
+		   const u8 *buf, size_t len)
+{
+	const u8 *sda;
+	u16 sda_len;
+	unsigned int skip;
+
+	if (!de->num_service)
+		return;
+
+	wpa_printf(MSG_DEBUG, "NAN: RX SDF from " MACSTR " freq=%u len=%zu",
+		   MAC2STR(peer_addr), freq, len);
+
+	wpa_hexdump(MSG_MSGDUMP, "NAN: SDF payload", buf, len);
+
+	for (skip = 0; ; skip++) {
+		sda = nan_de_get_attr(buf, len, NAN_ATTR_SDA, skip);
+		if (!sda)
+			break;
+
+		sda++;
+		sda_len = WPA_GET_LE16(sda);
+		sda += 2;
+		nan_de_rx_sda(de, peer_addr, freq, buf, len, sda, sda_len);
+	}
+}
+
+
+static int nan_de_get_handle(struct nan_de *de)
+{
+	int i = de->next_handle;
+
+	if (de->num_service >= NAN_DE_MAX_SERVICE)
+		goto fail;
+
+	do {
+		if (!de->service[i]) {
+			de->next_handle = (i + 1) % NAN_DE_MAX_SERVICE;
+			return i + 1;
+		}
+		i = (i + 1) % NAN_DE_MAX_SERVICE;
+	} while (i != de->next_handle);
+
+fail:
+	wpa_printf(MSG_DEBUG, "NAN: No more room for a new service");
+	return -1;
+}
+
+
+static int nan_de_derive_service_id(struct nan_de_service *srv)
+{
+	u8 hash[SHA256_MAC_LEN];
+	char *name, *pos;
+	int ret;
+	const u8 *addr[1];
+	size_t len[1];
+
+	name = os_strdup(srv->service_name);
+	if (!name)
+		return -1;
+	pos = name;
+	while (*pos) {
+		*pos = tolower(*pos);
+		pos++;
+	}
+
+	addr[0] = (u8 *) name;
+	len[0] = os_strlen(name);
+	ret = sha256_vector(1, addr, len, hash);
+	os_free(name);
+	if (ret == 0)
+		os_memcpy(srv->service_id, hash, NAN_SERVICE_ID_LEN);
+
+	return ret;
+}
+
+
+int nan_de_publish(struct nan_de *de, const char *service_name,
+		   enum nan_service_protocol_type srv_proto_type,
+		   const struct wpabuf *ssi, const struct wpabuf *elems,
+		   struct nan_publish_params *params)
+{
+	int publish_id;
+	struct nan_de_service *srv;
+
+	if (!service_name) {
+		wpa_printf(MSG_DEBUG, "NAN: Publish() - no service_name");
+		return -1;
+	}
+
+	publish_id = nan_de_get_handle(de);
+	if (publish_id < 1)
+		return -1;
+
+	srv = os_zalloc(sizeof(*srv));
+	if (!srv)
+		return -1;
+	srv->type = NAN_DE_PUBLISH;
+	srv->freq = srv->default_freq = params->freq;
+	srv->service_name = os_strdup(service_name);
+	if (!srv->service_name)
+		goto fail;
+	if (nan_de_derive_service_id(srv) < 0)
+		goto fail;
+	os_memcpy(&srv->publish, params, sizeof(*params));
+
+	if (params->freq_list) {
+		size_t len;
+
+		len = (int_array_len(params->freq_list) + 1) * sizeof(int);
+		srv->freq_list = os_memdup(params->freq_list, len);
+		if (!srv->freq_list)
+			goto fail;
+	}
+	srv->publish.freq_list = NULL;
+
+	srv->srv_proto_type = srv_proto_type;
+	if (ssi) {
+		srv->ssi = wpabuf_dup(ssi);
+		if (!srv->ssi)
+			goto fail;
+	}
+	if (elems) {
+		srv->elems = wpabuf_dup(elems);
+		if (!srv->elems)
+			goto fail;
+	}
+
+	/* Prepare for single and multi-channel states; starting with
+	 * single channel */
+	srv->first_multi_chan = true;
+	nan_de_start_new_publish_state(srv, true);
+
+	wpa_printf(MSG_DEBUG, "NAN: Assigned new publish handle %d for %s",
+		   publish_id, service_name);
+	srv->id = publish_id;
+	nan_de_add_srv(de, srv);
+	nan_de_run_timer(de);
+	return publish_id;
+fail:
+	nan_de_service_free(srv);
+	return -1;
+}
+
+
+void nan_de_cancel_publish(struct nan_de *de, int publish_id)
+{
+	struct nan_de_service *srv;
+
+	wpa_printf(MSG_DEBUG, "NAN: CancelPublish(publish_id=%d)", publish_id);
+
+	if (publish_id < 1 || publish_id > NAN_DE_MAX_SERVICE)
+		return;
+	srv = de->service[publish_id - 1];
+	if (!srv || srv->type != NAN_DE_PUBLISH)
+		return;
+	nan_de_del_srv(de, srv, NAN_DE_REASON_USER_REQUEST);
+}
+
+
+int nan_de_update_publish(struct nan_de *de, int publish_id,
+			  const struct wpabuf *ssi)
+{
+	struct nan_de_service *srv;
+
+	wpa_printf(MSG_DEBUG, "NAN: UpdatePublish(publish_id=%d)", publish_id);
+
+	if (publish_id < 1 || publish_id > NAN_DE_MAX_SERVICE)
+		return -1;
+	srv = de->service[publish_id - 1];
+	if (!srv || srv->type != NAN_DE_PUBLISH)
+		return -1;
+
+	wpabuf_free(srv->ssi);
+	srv->ssi = NULL;
+	if (!ssi)
+		return 0;
+	srv->ssi = wpabuf_dup(ssi);
+	if (!srv->ssi)
+		return -1;
+	return 0;
+}
+
+
+int nan_de_subscribe(struct nan_de *de, const char *service_name,
+		     enum nan_service_protocol_type srv_proto_type,
+		     const struct wpabuf *ssi, const struct wpabuf *elems,
+		     struct nan_subscribe_params *params)
+{
+	int subscribe_id;
+	struct nan_de_service *srv;
+
+	if (!service_name) {
+		wpa_printf(MSG_DEBUG, "NAN: Subscribe() - no service_name");
+		return -1;
+	}
+
+	subscribe_id = nan_de_get_handle(de);
+	if (subscribe_id < 1)
+		return -1;
+
+	srv = os_zalloc(sizeof(*srv));
+	if (!srv)
+		return -1;
+	srv->type = NAN_DE_SUBSCRIBE;
+	srv->freq = params->freq;
+	srv->service_name = os_strdup(service_name);
+	if (!srv->service_name)
+		goto fail;
+	if (nan_de_derive_service_id(srv) < 0)
+		goto fail;
+	os_memcpy(&srv->subscribe, params, sizeof(*params));
+	srv->srv_proto_type = srv_proto_type;
+	if (ssi) {
+		srv->ssi = wpabuf_dup(ssi);
+		if (!srv->ssi)
+			goto fail;
+	}
+	if (elems) {
+		srv->elems = wpabuf_dup(elems);
+		if (!srv->elems)
+			goto fail;
+	}
+
+	wpa_printf(MSG_DEBUG, "NAN: Assigned new subscribe handle %d for %s",
+		   subscribe_id, service_name);
+	srv->id = subscribe_id;
+	nan_de_add_srv(de, srv);
+	nan_de_run_timer(de);
+	return subscribe_id;
+fail:
+	nan_de_service_free(srv);
+	return -1;
+}
+
+
+void nan_de_cancel_subscribe(struct nan_de *de, int subscribe_id)
+{
+	struct nan_de_service *srv;
+
+	if (subscribe_id < 1 || subscribe_id > NAN_DE_MAX_SERVICE)
+		return;
+	srv = de->service[subscribe_id - 1];
+	if (!srv || srv->type != NAN_DE_SUBSCRIBE)
+		return;
+	nan_de_del_srv(de, srv, NAN_DE_REASON_USER_REQUEST);
+}
+
+
+int nan_de_transmit(struct nan_de *de, int handle,
+		    const struct wpabuf *ssi, const struct wpabuf *elems,
+		    const u8 *peer_addr, u8 req_instance_id)
+{
+	struct nan_de_service *srv;
+
+	if (handle < 1 || handle > NAN_DE_MAX_SERVICE)
+		return -1;
+
+	srv = de->service[handle - 1];
+	if (!srv)
+		return -1;
+
+	nan_de_tx_sdf(de, srv, 100, NAN_SRV_CTRL_FOLLOW_UP,
+		      peer_addr, req_instance_id, ssi);
+
+	os_get_reltime(&srv->last_followup);
+	return 0;
+}
diff --git a/src/common/nan_de.h b/src/common/nan_de.h
new file mode 100644
index 0000000..6223506
--- /dev/null
+++ b/src/common/nan_de.h
@@ -0,0 +1,145 @@
+/*
+ * NAN Discovery Engine
+ * 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_DE_H
+#define NAN_DE_H
+
+#include "nan.h"
+
+/* Maximum number of active local publish and subscribe instances */
+#ifndef NAN_DE_MAX_SERVICE
+#define NAN_DE_MAX_SERVICE 20
+#endif /* NAN_DE_MAX_SERVICE */
+
+struct nan_de;
+
+enum nan_de_reason {
+	NAN_DE_REASON_TIMEOUT,
+	NAN_DE_REASON_USER_REQUEST,
+	NAN_DE_REASON_FAILURE,
+};
+
+struct nan_callbacks {
+	void *ctx;
+
+	int (*tx)(void *ctx, unsigned int freq, unsigned int wait_time,
+		  const u8 *dst, const u8 *src, const u8 *bssid,
+		  const struct wpabuf *buf);
+	int (*listen)(void *ctx, unsigned int freq, unsigned int duration);
+
+	/* NAN DE Events */
+	void (*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);
+
+	void (*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);
+
+	void (*publish_terminated)(void *ctx, int publish_id,
+				    enum nan_de_reason reason);
+
+	void (*subscribe_terminated)(void *ctx, int subscribe_id,
+				     enum nan_de_reason reason);
+
+	void (*receive)(void *ctx, int id, int peer_instance_id,
+			const u8 *ssi, size_t ssi_len,
+			const u8 *peer_addr);
+};
+
+struct nan_de * nan_de_init(const u8 *nmi, bool ap,
+			    const struct nan_callbacks *cb);
+void nan_de_flush(struct nan_de *de);
+void nan_de_deinit(struct nan_de *de);
+
+void nan_de_listen_started(struct nan_de *de, unsigned int freq,
+			   unsigned int duration);
+void nan_de_listen_ended(struct nan_de *de, unsigned int freq);
+void nan_de_tx_status(struct nan_de *de, unsigned int freq, const u8 *dst);
+void nan_de_tx_wait_ended(struct nan_de *de);
+
+void nan_de_rx_sdf(struct nan_de *de, const u8 *peer_addr, unsigned int freq,
+		   const u8 *buf, size_t len);
+
+struct nan_publish_params {
+	/* configuration_parameters */
+
+	/* Publish type */
+	bool unsolicited;
+	bool solicited;
+
+	/* Solicited transmission type */
+	bool solicited_multicast;
+
+	/* Time to live (in seconds); 0 = one TX only */
+	unsigned int ttl;
+
+	/* Event conditions */
+	bool disable_events;
+
+	/* Further Service Discovery flag */
+	bool fsd;
+
+	/* Further Service Discovery function */
+	bool fsd_gas;
+
+	/* Default frequency (defaultPublishChannel) */
+	unsigned int freq;
+
+	/* Multi-channel frequencies (publishChannelList) */
+	const int *freq_list;
+
+	/* Announcement period in ms; 0 = use default */
+	unsigned int announcement_period;
+};
+
+/* Returns -1 on failure or >0 publish_id */
+int nan_de_publish(struct nan_de *de, const char *service_name,
+		   enum nan_service_protocol_type srv_proto_type,
+		   const struct wpabuf *ssi, const struct wpabuf *elems,
+		   struct nan_publish_params *params);
+
+void nan_de_cancel_publish(struct nan_de *de, int publish_id);
+
+int nan_de_update_publish(struct nan_de *de, int publish_id,
+			  const struct wpabuf *ssi);
+
+struct nan_subscribe_params {
+	/* configuration_parameters */
+
+	/* Subscribe type */
+	bool active;
+
+	/* Time to live (in seconds); 0 = until first result */
+	unsigned int ttl;
+
+	/* Selected frequency */
+	unsigned int freq;
+
+	/* Query period in ms; 0 = use default */
+	unsigned int query_period;
+};
+
+/* Returns -1 on failure or >0 subscribe_id */
+int nan_de_subscribe(struct nan_de *de, const char *service_name,
+		     enum nan_service_protocol_type srv_proto_type,
+		     const struct wpabuf *ssi, const struct wpabuf *elems,
+		     struct nan_subscribe_params *params);
+
+void nan_de_cancel_subscribe(struct nan_de *de, int subscribe_id);
+
+/* handle = publish_id or subscribe_id
+ * req_instance_id = peer publish_id or subscribe_id */
+int nan_de_transmit(struct nan_de *de, int handle,
+		    const struct wpabuf *ssi, const struct wpabuf *elems,
+		    const u8 *peer_addr, u8 req_instance_id);
+
+#endif /* NAN_DE_H */
diff --git a/src/common/ptksa_cache.c b/src/common/ptksa_cache.c
index 3b5c0b8..c00f288 100644
--- a/src/common/ptksa_cache.c
+++ b/src/common/ptksa_cache.c
@@ -141,7 +141,7 @@
 		return NULL;
 
 	dl_list_for_each(e, &ptksa->ptksa, struct ptksa_cache_entry, list) {
-		if ((!addr || os_memcmp(e->addr, addr, ETH_ALEN) == 0) &&
+		if ((!addr || ether_addr_equal(e->addr, addr)) &&
 		    (cipher == WPA_CIPHER_NONE || cipher == e->cipher))
 			return e;
 	}
@@ -238,7 +238,7 @@
 
 	dl_list_for_each_safe(e, next, &ptksa->ptksa, struct ptksa_cache_entry,
 			      list) {
-		if ((!addr || os_memcmp(e->addr, addr, ETH_ALEN) == 0) &&
+		if ((!addr || ether_addr_equal(e->addr, addr)) &&
 		    (cipher == WPA_CIPHER_NONE || cipher == e->cipher)) {
 			wpa_printf(MSG_DEBUG,
 				   "Flush PTKSA cache entry for " MACSTR,
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index 7620f03..a5bbc78 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -1024,6 +1024,30 @@
  *
  *	The attributes used with this subcommand are defined in
  *	enum qca_wlan_vendor_attr_tx_latency.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_REGULATORY_TPC_INFO: Vendor command is used to
+ *	query transmit power information on STA interface from the driver for a
+ *	connected AP. The attributes included in response are defined in
+ *	enum qca_wlan_vendor_attr_tpc_links. In case of MLO STA, multiple links
+ *	TPC info may be returned. The information includes regulatory maximum
+ *	transmit power limit, AP local power constraint advertised from AP's
+ *	Beacon and Probe Response frames. For PSD power mode, the information
+ *	includes PSD power levels for each subchannel of operating bandwidth.
+ *	The information is driver calculated power limits based on the current
+ *	regulatory domain, AP local power constraint, and other IEs. The
+ *	information will be set to target. Target will decide the final TX power
+ *	based on this and chip specific power conformance test limits (CTL), and
+ *	SAR limits.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_FW_PAGE_FAULT_REPORT: Event indication from the
+ *	driver to user space which is carrying firmware page fault related
+ *	summary report. The attributes for this command are defined in
+ *	enum qca_wlan_vendor_attr_fw_page_fault_report.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_DISASSOC_PEER: Event indication from the driver
+ *	to user space to disassociate with a peer based on the peer MAC address
+ *	provided. Specify the peer MAC address in
+ *	QCA_WLAN_VENDOR_ATTR_MAC_ADDR. For MLO, MLD MAC address is provided.
  */
 enum qca_nl80211_vendor_subcmds {
 	QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -1242,6 +1266,12 @@
 	/* 232 - reserved for QCA */
 	QCA_NL80211_VENDOR_SUBCMD_TX_LATENCY = 233,
 	/* 234 - reserved for QCA */
+	QCA_NL80211_VENDOR_SUBCMD_SDWF_PHY_OPS = 235,
+	QCA_NL80211_VENDOR_SUBCMD_SDWF_DEV_OPS = 236,
+	QCA_NL80211_VENDOR_SUBCMD_REGULATORY_TPC_INFO = 237,
+	QCA_NL80211_VENDOR_SUBCMD_FW_PAGE_FAULT_REPORT = 238,
+	QCA_NL80211_VENDOR_SUBCMD_FLOW_POLICY = 239,
+	QCA_NL80211_VENDOR_SUBCMD_DISASSOC_PEER = 240,
 };
 
 /* Compatibility defines for previously used subcmd names.
@@ -1795,6 +1825,11 @@
  * scoring. In case scan was performed on a partial set of channels configured
  * with this command within last QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME
  * (in ms), scan only the remaining channels.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ACS_LINK_ID: Mandatory on AP MLD (u8).
+ * Used with command to configure ACS operation for a specific link affiliated
+ * to an AP MLD.
+ *
  */
 enum qca_wlan_vendor_attr_acs_offload {
 	QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0,
@@ -1818,6 +1853,7 @@
 	QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP = 18,
 	QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED = 19,
 	QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME = 20,
+	QCA_WLAN_VENDOR_ATTR_ACS_LINK_ID = 21,
 
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST,
@@ -2179,7 +2215,8 @@
  * &enum qca_tsf_cmd.
  * @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Optional (u64)
  * This attribute contains TSF timer value. This attribute is only available
- * in %QCA_TSF_GET or %QCA_TSF_SYNC_GET response.
+ * in %QCA_TSF_GET, %QCA_TSF_SYNC_GET or %QCA_TSF_SYNC_GET_CSA_TIMESTAMP
+ * response.
  * @QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE: Optional (u64)
  * This attribute contains SOC timer value at TSF capture. This attribute is
  * only available in %QCA_TSF_GET or %QCA_TSF_SYNC_GET response.
@@ -2223,6 +2260,12 @@
  * userspace can query the TSF and host time mapping via the %QCA_TSF_GET
  * command.
  * @QCA_TSF_SYNC_STOP: Stop periodic TSF sync feature.
+ * @QCA_TSF_SYNC_GET_CSA_TIMESTAMP: Get TSF timestamp when AP will move and
+ * starts beaconing on a new channel. The driver synchronously responds with the
+ * TSF value using attribute %QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE. Userspace
+ * gets the valid CSA TSF after receiving %NL80211_CMD_CH_SWITCH_STARTED_NOTIFY
+ * on the AP interface. This TSF can be sent via OOB mechanism to connected
+ * clients.
  */
 enum qca_tsf_cmd {
 	QCA_TSF_CAPTURE,
@@ -2232,6 +2275,7 @@
 	QCA_TSF_AUTO_REPORT_DISABLE,
 	QCA_TSF_SYNC_START,
 	QCA_TSF_SYNC_STOP,
+	QCA_TSF_SYNC_GET_CSA_TIMESTAMP,
 };
 
 /**
@@ -2373,6 +2417,10 @@
  *	QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH as the priority of vendor scan.
  * @QCA_WLAN_VENDOR_ATTR_SCAN_PAD: Attribute used for padding for 64-bit
  *	alignment.
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_LINK_ID: This u8 attribute is used for OBSS scan
+ *	when AP is operating as MLD to specify which link is requesting the
+ *	scan or which link the scan result is for. No need of this attribute
+ *	in other cases.
  */
 enum qca_wlan_vendor_attr_scan {
 	QCA_WLAN_VENDOR_ATTR_SCAN_INVALID_PARAM = 0,
@@ -2390,6 +2438,7 @@
 	QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME = 12,
 	QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY = 13,
 	QCA_WLAN_VENDOR_ATTR_SCAN_PAD = 14,
+	QCA_WLAN_VENDOR_ATTR_SCAN_LINK_ID = 15,
 	QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_SCAN_MAX =
 	QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST - 1
@@ -3302,6 +3351,16 @@
 	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_COEX_TRAFFIC_SHAPING_MODE = 105,
 
+	/* 8-bit unsigned value.
+	 *
+	 * This attribute is used to specify whether an associated peer is a QCA
+	 * device. The associated peer is specified with
+	 * QCA_WLAN_VENDOR_ATTR_CONFIG_PEER_MAC. For MLO cases, the MLD MAC
+	 * address of the peer is used.
+	 * 1 - QCA device, 0 - non-QCA device.
+	 */
+	QCA_WLAN_VENDOR_ATTR_CONFIG_QCA_PEER = 106,
+
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_CONFIG_MAX =
@@ -9989,6 +10048,13 @@
 	 */
 	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MLD_ID_ML_PROBE_REQ = 72,
 
+	/* 8-bit unsigned value to configure the SCS traffic description
+	 * support in the EHT capabilities of an Association Request frame.
+	 * 1-enable, 0-disable
+	 * This attribute is used to configure the testbed device.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_SCS_TRAFFIC_SUPPORT = 73,
+
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX =
@@ -14169,12 +14235,14 @@
  * @QCA_WLAN_RATEMASK_PARAMS_TYPE_HT: HT rate mask config
  * @QCA_WLAN_RATEMASK_PARAMS_TYPE_VHT: VHT rate mask config
  * @QCA_WLAN_RATEMASK_PARAMS_TYPE_HE: HE rate mask config
+ * @QCA_WLAN_RATEMASK_PARAMS_TYPE_EHT: EHT rate mask config
  */
 enum qca_wlan_ratemask_params_type {
 	QCA_WLAN_RATEMASK_PARAMS_TYPE_CCK_OFDM = 0,
 	QCA_WLAN_RATEMASK_PARAMS_TYPE_HT = 1,
 	QCA_WLAN_RATEMASK_PARAMS_TYPE_VHT = 2,
 	QCA_WLAN_RATEMASK_PARAMS_TYPE_HE = 3,
+	QCA_WLAN_RATEMASK_PARAMS_TYPE_EHT = 4,
 };
 
 /**
@@ -14969,12 +15037,25 @@
  * CTL group but user can choose up to 3 SAR set index only, as the top half
  * of the SAR index (0 to 2) is used for non DBS purpose and the bottom half of
  * the SAR index (3 to 5) is used for DBS mode.
+ *
+ * @QCA_WLAN_VENDOR_SAR_VERSION_4: The firmware supports SAR version 4,
+ * known as SAR Smart Transmit (STX) mode. STX is time averaging algorithmic
+ * for power limit computation in collaboration with WWAN.
+ * In STX mode, firmware has 41 indexes and there is no ctl grouping uses.
+ *
+ * @QCA_WLAN_VENDOR_SAR_VERSION_5: The firmware supports SAR version 5,
+ * known as TAS (Time Averaging SAR) mode. In TAS mode, as name implies
+ * instead of fixed static SAR power limit firmware uses time averaging
+ * to adjust the SAR limit dynamically. It is wlan soc standalone mechanism.
+ * In this mode firmware has up to 43 indexes.
  */
 enum qca_wlan_vendor_sar_version {
 	QCA_WLAN_VENDOR_SAR_VERSION_INVALID = 0,
 	QCA_WLAN_VENDOR_SAR_VERSION_1 = 1,
 	QCA_WLAN_VENDOR_SAR_VERSION_2 = 2,
 	QCA_WLAN_VENDOR_SAR_VERSION_3 = 3,
+	QCA_WLAN_VENDOR_SAR_VERSION_4 = 4,
+	QCA_WLAN_VENDOR_SAR_VERSION_5 = 5,
 };
 
 /**
@@ -16602,4 +16683,115 @@
 	QCA_CHAN_WIDTH_UPDATE_TYPE_TX_RX_EXT = 2,
 };
 
+/**
+ * enum qca_wlan_vendor_attr_tpc_pwr_level - Definition of attributes
+ * used inside nested attribute %QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_FREQUENCY: u32 channel center
+ * frequency (MHz): If PSD power, carries one 20 MHz sub-channel center
+ * frequency. If non PSD power, carries either 20 MHz bandwidth's center
+ * channel frequency or 40 MHz bandwidth's center channel frequency
+ * (or 80/160 MHz bandwidth's center channel frequency).
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_TX_POWER: s8 transmit power limit (dBm).
+ * If PSD power, carries PSD power value of the
+ * QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_FREQUENCY mentioned sub-channel.
+ * If non PSD power, carries EIRP power value of bandwidth mentioned
+ * by QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_FREQUENCY center frequency.
+ */
+enum qca_wlan_vendor_attr_tpc_pwr_level {
+	QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_FREQUENCY = 1,
+	QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_TX_POWER = 2,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_MAX =
+	QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_tpc - Definition of link attributes
+ * used inside nested attribute %QCA_WLAN_VENDOR_ATTR_TPC_LINKS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TPC_BSSID: 6-bytes AP BSSID.
+ * For MLO STA, AP BSSID indicates the AP's link address.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TPC_PSD_POWER: PSD power flag
+ * Indicates using PSD power mode if this flag is present.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TPC_EIRP_POWER: s8 Regulatory EIRP power
+ * value in dBm
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TPC_POWER_TYPE_6GHZ: u8 power type of 6 GHz
+ * AP, refer to Table E-12-Regulatory Info subfield encoding in
+ * IEEE P802.11-REVme/D4.0. Only present if link is connected to 6 GHz AP.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TPC_AP_CONSTRAINT_POWER: u8 Local Power Constraint
+ * (dBm) advertised by AP in Power Constraint element, refer to
+ * IEEE Std 802.11-2020, 9.4.2.13 Power Constraint element.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL: A nested attribute containing
+ * attributes defined by enum qca_wlan_vendor_attr_tpc_pwr_level.
+ * If PSD power, each power level describes each 20 MHz subchannel PSD
+ * power value. If non PSD power, each power level describes each supported
+ * bandwidth's EIRP power value (up to Max bandwidth of AP operating on),
+ * each level attribute contains corresponding bandwidth's center channel
+ * frequency and its EIRP power value.
+ */
+enum qca_wlan_vendor_attr_tpc {
+	QCA_WLAN_VENDOR_ATTR_TPC_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_TPC_BSSID = 1,
+	QCA_WLAN_VENDOR_ATTR_TPC_PSD_POWER = 2,
+	QCA_WLAN_VENDOR_ATTR_TPC_EIRP_POWER = 3,
+	QCA_WLAN_VENDOR_ATTR_TPC_POWER_TYPE_6GHZ = 4,
+	QCA_WLAN_VENDOR_ATTR_TPC_AP_CONSTRAINT_POWER = 5,
+	QCA_WLAN_VENDOR_ATTR_TPC_PWR_LEVEL = 6,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_TPC_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_TPC_MAX =
+	QCA_WLAN_VENDOR_ATTR_TPC_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_tpc_links - Definition of attributes
+ * for %QCA_NL80211_VENDOR_SUBCMD_REGULATORY_TPC_INFO subcommand
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TPC_LINKS: A nested attribute containing
+ * per-link TPC information of all the active links of MLO STA.
+ * For non MLO STA, only one link TPC information will be returned
+ * for connected AP in this nested attribute.
+ * The attributes used inside this nested attributes are defined
+ * in enum qca_wlan_vendor_attr_tpc.
+ */
+enum qca_wlan_vendor_attr_tpc_links {
+	QCA_WLAN_VENDOR_ATTR_TPC_LINKS_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_TPC_LINKS = 1,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_TPC_LINKS_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_TPC_LINKS_MAX =
+	QCA_WLAN_VENDOR_ATTR_TPC_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_fw_page_fault_report - Used by the vendor
+ * command %QCA_NL80211_VENDOR_SUBCMD_FW_PAGE_FAULT_REPORT.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_FW_PAGE_FAULT_REPORT_DATA: The binary blob data
+ * associated with the firmware page fault that is expected to contain the
+ * required dump to analyze frequent page faults.
+ * NLA_BINARY attribute, the maximum size is 1024 bytes.
+ */
+enum qca_wlan_vendor_attr_fw_page_fault_report {
+	QCA_WLAN_VENDOR_ATTR_FW_PAGE_FAULT_REPORT_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_FW_PAGE_FAULT_REPORT_DATA = 1,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_FW_PAGE_FAULT_REPORT_LAST,
+	QCA_WLAN_VENDOR_ATTR_FW_PAGE_FAULT_REPORT_MAX =
+	QCA_WLAN_VENDOR_ATTR_FW_PAGE_FAULT_REPORT_LAST - 1,
+};
+
 #endif /* QCA_VENDOR_H */
diff --git a/src/common/sae.c b/src/common/sae.c
index d4a196f..f1c164e 100644
--- a/src/common/sae.c
+++ b/src/common/sae.c
@@ -458,7 +458,7 @@
 		       * mask */
 	u8 mask;
 	struct crypto_bignum *pwe;
-	size_t prime_len = sae->tmp->prime_len * 8;
+	size_t prime_len = sae->tmp->prime_len;
 	u8 *pwe_buf;
 
 	crypto_bignum_deinit(sae->tmp->pwe_ffc, 1);
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index d897e0e..c82fd0e 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -1329,8 +1329,7 @@
 		if (fte_len < 255) {
 			res = wpa_ft_parse_fte(key_mgmt, fte, fte_len, parse);
 		} else {
-			parse->fte_buf = ieee802_11_defrag_data(fte, fte_len,
-								false);
+			parse->fte_buf = ieee802_11_defrag(fte, fte_len, false);
 			if (!parse->fte_buf)
 				goto fail;
 			res = wpa_ft_parse_fte(key_mgmt,
@@ -2894,7 +2893,7 @@
 }
 
 
-int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid)
+int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid, bool replace)
 {
 	u8 *start, *end, *rpos, *rend;
 	int added = 0;
@@ -2957,12 +2956,12 @@
 		if (rend - rpos < 2)
 			return -1;
 		num_pmkid = WPA_GET_LE16(rpos);
+		if (num_pmkid * PMKID_LEN > rend - rpos - 2)
+			return -1;
 		/* PMKID-Count was included; use it */
-		if (num_pmkid != 0) {
+		if (replace && num_pmkid != 0) {
 			u8 *after;
 
-			if (num_pmkid * PMKID_LEN > rend - rpos - 2)
-				return -1;
 			/*
 			 * PMKID may have been included in RSN IE in
 			 * (Re)Association Request frame, so remove the old
@@ -2975,8 +2974,9 @@
 			os_memmove(rpos + 2, after, end - after);
 			start[1] -= num_pmkid * PMKID_LEN;
 			added -= num_pmkid * PMKID_LEN;
+			num_pmkid = 0;
 		}
-		WPA_PUT_LE16(rpos, 1);
+		WPA_PUT_LE16(rpos, num_pmkid + 1);
 		rpos += 2;
 		os_memmove(rpos + PMKID_LEN, rpos, end + added - rpos);
 		os_memcpy(rpos, pmkid, PMKID_LEN);
diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
index 1269bf9..a2c7033 100644
--- a/src/common/wpa_common.h
+++ b/src/common/wpa_common.h
@@ -555,7 +555,7 @@
 int wpa_compare_rsn_ie(int ft_initial_assoc,
 		       const u8 *ie1, size_t ie1len,
 		       const u8 *ie2, size_t ie2len);
-int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid);
+int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid, bool replace);
 
 #define MAX_NUM_MLO_LINKS 15
 
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 416e0d6..c5bb9ab 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -87,6 +87,8 @@
 #define WPA_EVENT_BEACON_LOSS "CTRL-EVENT-BEACON-LOSS "
 /** Regulatory domain channel */
 #define WPA_EVENT_REGDOM_CHANGE "CTRL-EVENT-REGDOM-CHANGE "
+/** Regulatory beacon hint */
+#define WPA_EVENT_REGDOM_BEACON_HINT "CTRL-EVENT-REGDOM-BEACON-HINT "
 /** Channel switch started (followed by freq=<MHz> and other channel parameters)
  */
 #define WPA_EVENT_CHANNEL_SWITCH_STARTED "CTRL-EVENT-STARTED-CHANNEL-SWITCH "
@@ -230,6 +232,13 @@
 #define DPP_EVENT_PB_RESULT "DPP-PB-RESULT "
 #define DPP_EVENT_RELAY_NEEDS_CONTROLLER "DPP-RELAY-NEEDS-CONTROLLER "
 
+/* Wi-Fi Aware (NAN USD) events */
+#define NAN_DISCOVERY_RESULT "NAN-DISCOVERY-RESULT "
+#define NAN_REPLIED "NAN-REPLIED "
+#define NAN_PUBLISH_TERMINATED "NAN-PUBLISH-TERMINATED "
+#define NAN_SUBSCRIBE_TERMINATED "NAN-SUBSCRIBE-TERMINATED "
+#define NAN_RECEIVE "NAN-RECEIVE "
+
 /* MESH events */
 #define MESH_GROUP_STARTED "MESH-GROUP-STARTED "
 #define MESH_GROUP_REMOVED "MESH-GROUP-REMOVED "