Revert "Revert "[wpa_supplicant] cumilative patch from commit 3a..."

Revert submission 28102966-revert-26533062-Supplicant_merge_June24-CUATTSRBBR

Reason for revert: Fixed the regression issue (ag/28389573)

Reverted changes: /q/submissionid:28102966-revert-26533062-Supplicant_merge_June24-CUATTSRBBR

Bug: 329004037
Test: Turn ON/OFF SoftAp multiple times

Change-Id: Ibfff2a847be5678f1a6d77e28506a05936812a91
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index c1be660..22b694c 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -13,10 +13,12 @@
 #include "common/ieee802_11_defs.h"
 #include "drivers/driver.h"
 #include "eap_peer/eap.h"
+#include "rsn_supp/wpa.h"
 #include "wpa_supplicant_i.h"
 #include "config.h"
 #include "notify.h"
 #include "scan.h"
+#include "bssid_ignore.h"
 #include "bss.h"
 
 static void wpa_bss_set_hessid(struct wpa_bss *bss)
@@ -263,7 +265,7 @@
 	if (bssid && !wpa_supplicant_filter_bssid_match(wpa_s, bssid))
 		return NULL;
 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
-		if ((!bssid || os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0) &&
+		if ((!bssid || ether_addr_equal(bss->bssid, bssid)) &&
 		    bss->ssid_len == ssid_len &&
 		    os_memcmp(bss->ssid, ssid, ssid_len) == 0)
 			return bss;
@@ -358,12 +360,11 @@
 #ifdef CONFIG_P2P
 	u8 addr[ETH_ALEN];
 
-	if (os_memcmp(bss->bssid, wpa_s->pending_join_iface_addr,
-		      ETH_ALEN) == 0)
+	if (ether_addr_equal(bss->bssid, wpa_s->pending_join_iface_addr))
 		return true;
 	if (!is_zero_ether_addr(wpa_s->pending_join_dev_addr) &&
 	    p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len, addr) == 0 &&
-	    os_memcmp(addr, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0)
+	    ether_addr_equal(addr, wpa_s->pending_join_dev_addr))
 		return true;
 #endif /* CONFIG_P2P */
 	return false;
@@ -406,8 +407,8 @@
 		return 0; /* SSID has changed */
 
 	if (!is_zero_ether_addr(bss->bssid) &&
-	    (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) == 0 ||
-	     os_memcmp(bss->bssid, wpa_s->pending_bssid, ETH_ALEN) == 0))
+	    (ether_addr_equal(bss->bssid, wpa_s->bssid) ||
+	     ether_addr_equal(bss->bssid, wpa_s->pending_bssid)))
 		return 1;
 
 	if (!wpa_s->valid_links)
@@ -417,7 +418,7 @@
 		if (!(wpa_s->valid_links & BIT(i)))
 			continue;
 
-		if (os_memcmp(bss->bssid, wpa_s->links[i].bssid, ETH_ALEN) == 0)
+		if (ether_addr_equal(bss->bssid, wpa_s->links[i].bssid))
 			return 1;
 	}
 
@@ -717,7 +718,8 @@
 	dl_list_del(&bss->list);
 #ifdef CONFIG_P2P
 	if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) &&
-	    !wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE)) {
+	    !wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE) &&
+	    !(changes & WPA_BSS_FREQ_CHANGED_FLAG)) {
 		/*
 		 * This can happen when non-P2P station interface runs a scan
 		 * without P2P IE in the Probe Request frame. P2P GO would reply
@@ -1101,7 +1103,7 @@
 	if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
 		return NULL;
 	dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
-		if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
+		if (ether_addr_equal(bss->bssid, bssid))
 			return bss;
 	}
 	return NULL;
@@ -1126,7 +1128,7 @@
 	if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
 		return NULL;
 	dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
-		if (os_memcmp(bss->bssid, bssid, ETH_ALEN) != 0)
+		if (!ether_addr_equal(bss->bssid, bssid))
 			continue;
 		if (found == NULL ||
 		    os_reltime_before(&found->last_update, &bss->last_update))
@@ -1155,7 +1157,7 @@
 		u8 addr[ETH_ALEN];
 		if (p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len,
 				       addr) != 0 ||
-		    os_memcmp(addr, dev_addr, ETH_ALEN) != 0)
+		    !ether_addr_equal(addr, dev_addr))
 			continue;
 		if (!found ||
 		    os_reltime_before(&found->last_update, &bss->last_update))
@@ -1222,22 +1224,6 @@
 
 
 /**
- * wpa_bss_get_ie_nth - Fetch a specified information element from a BSS entry
- * @bss: BSS table entry
- * @ie: Information element identitifier (WLAN_EID_*)
- * @nth: Return the nth element of the requested type (2 returns the second)
- * Returns: Pointer to the information element (id field) or %NULL if not found
- *
- * This function returns the nth matching information element in the BSS
- * entry.
- */
-const u8 * wpa_bss_get_ie_nth(const struct wpa_bss *bss, u8 ie, int nth)
-{
-	return get_ie_nth(wpa_bss_ie_ptr(bss), bss->ie_len, ie, nth);
-}
-
-
-/**
  * wpa_bss_get_ie_ext - Fetch a specified extended IE from a BSS entry
  * @bss: BSS table entry
  * @ext: Information element extension identifier (WLAN_EID_EXT_*)
@@ -1496,29 +1482,12 @@
 }
 
 
-/**
- * wpa_bss_defrag_mle - Get a buffer holding a de-fragmented ML element
- * @bss: BSS table entry
- * @type: ML control type
- */
-struct wpabuf * wpa_bss_defrag_mle(const struct wpa_bss *bss, u8 type)
-{
-	struct ieee802_11_elems elems;
-	const u8 *pos = wpa_bss_ie_ptr(bss);
-	size_t len = bss->ie_len;
-
-	if (ieee802_11_parse_elems(pos, len, &elems, 1) == ParseFailed)
-		return NULL;
-
-	return ieee802_11_defrag_mle(&elems, type);
-}
-
-
 static void
 wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
 			     struct wpa_bss *bss, u8 mbssid_idx,
 			     const struct ieee80211_neighbor_ap_info *ap_info,
-			     size_t len, u16 *seen, u16 *missing)
+			     size_t len, u16 *seen, u16 *missing,
+			     struct wpa_ssid *ssid)
 {
 	const u8 *pos, *end;
 	const u8 *mld_params;
@@ -1542,12 +1511,15 @@
 	pos += sizeof(*ap_info);
 
 	for (i = 0; i < count; i++) {
+		u8 bss_params;
+
 		if (bss->n_mld_links >= MAX_NUM_MLD_LINKS)
 			return;
 
 		if (end - pos < ap_info->tbtt_info_len)
 			break;
 
+		bss_params = pos[1 + ETH_ALEN + 4];
 		mld_params = pos + mld_params_offset;
 
 		link_id = *(mld_params + 1) & EHT_ML_LINK_ID_MSK;
@@ -1557,23 +1529,30 @@
 				   "MLD: Reported link not part of MLD");
 		} else if (!(BIT(link_id) & *seen)) {
 			struct wpa_bss *neigh_bss =
-				wpa_bss_get_bssid(wpa_s, ap_info->data + 1);
+				wpa_bss_get_bssid(wpa_s, pos + 1);
 
 			*seen |= BIT(link_id);
 			wpa_printf(MSG_DEBUG, "MLD: mld ID=%u, link ID=%u",
 				   *mld_params, link_id);
 
-			if (neigh_bss) {
+			if (!neigh_bss) {
+				*missing |= BIT(link_id);
+			} else if ((!ssid ||
+				    (bss_params & (RNR_BSS_PARAM_SAME_SSID |
+						   RNR_BSS_PARAM_CO_LOCATED)) ||
+				    wpa_scan_res_match(wpa_s, 0, neigh_bss,
+						       ssid, 1, 0)) &&
+				   !wpa_bssid_ignore_is_listed(
+					   wpa_s, neigh_bss->bssid)) {
 				struct mld_link *l;
 
 				l = &bss->mld_links[bss->n_mld_links];
 				l->link_id = link_id;
-				os_memcpy(l->bssid, ap_info->data + 1,
-					  ETH_ALEN);
+				os_memcpy(l->bssid, pos + 1, ETH_ALEN);
 				l->freq = neigh_bss->freq;
+				l->disabled = mld_params[2] &
+					RNR_TBTT_INFO_MLD_PARAM2_LINK_DISABLED;
 				bss->n_mld_links++;
-			} else {
-				*missing |= BIT(link_id);
 			}
 		}
 
@@ -1590,6 +1569,8 @@
  * @link_info: Array to store link information (or %NULL),
  *   should be initialized and #MAX_NUM_MLD_LINKS elements long
  * @missing_links: Result bitmask of links that were not discovered (or %NULL)
+ * @ssid: Target SSID (or %NULL)
+ * @ap_mld_id: On return would hold the corresponding AP MLD ID (or %NULL)
  * Returns: 0 on success or -1 for non-MLD or parsing failures
  *
  * Parses the Basic Multi-Link element of the BSS into @link_info using the scan
@@ -1600,13 +1581,15 @@
 int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
 				   struct wpa_bss *bss,
 				   u8 *ap_mld_addr,
-				   u16 *missing_links)
+				   u16 *missing_links,
+				   struct wpa_ssid *ssid,
+				   u8 *ap_mld_id)
 {
 	struct ieee802_11_elems elems;
 	struct wpabuf *mlbuf;
 	const struct element *elem;
 	u8 mbssid_idx = 0;
-	u8 ml_ie_len;
+	size_t ml_ie_len;
 	const struct ieee80211_eht_ml *eht_ml;
 	const struct eht_ml_basic_common_info *ml_basic_common_info;
 	u8 i, link_id;
@@ -1633,7 +1616,7 @@
 		return ret;
 	}
 
-	mlbuf = ieee802_11_defrag_mle(&elems, MULTI_LINK_CONTROL_TYPE_BASIC);
+	mlbuf = ieee802_11_defrag(elems.basic_mle, elems.basic_mle_len, true);
 	if (!mlbuf) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No Multi-Link element");
 		return ret;
@@ -1641,6 +1624,32 @@
 
 	ml_ie_len = wpabuf_len(mlbuf);
 
+	if (ssid) {
+		struct wpa_ie_data ie;
+
+		if (!elems.rsn_ie ||
+		    wpa_parse_wpa_ie(elems.rsn_ie - 2, 2 + elems.rsn_ie_len,
+				     &ie)) {
+			wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RSN element");
+			goto out;
+		}
+
+		if (!(ie.capabilities & WPA_CAPABILITY_MFPC) ||
+		    wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION) {
+			wpa_dbg(wpa_s, MSG_DEBUG,
+				"MLD: No management frame protection");
+			goto out;
+		}
+
+		ie.key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK |
+				 WPA_KEY_MGMT_PSK_SHA256);
+		if (!(ie.key_mgmt & ssid->key_mgmt)) {
+			wpa_dbg(wpa_s, MSG_DEBUG,
+				"MLD: No valid key management");
+			goto out;
+		}
+	}
+
 	/*
 	 * for ext ID + 2 control + common info len + MLD address +
 	 * link info
@@ -1720,7 +1729,7 @@
 
 			wpa_bss_parse_ml_rnr_ap_info(wpa_s, bss, mbssid_idx,
 						     ap_info, len, &seen,
-						     &missing);
+						     &missing, ssid);
 
 			pos += ap_info_len;
 			len -= ap_info_len;
@@ -1739,6 +1748,9 @@
 	if (missing_links)
 		*missing_links = missing;
 
+	if (ap_mld_id)
+		*ap_mld_id = mbssid_idx;
+
 	ret = 0;
 out:
 	wpabuf_free(mlbuf);
@@ -1769,7 +1781,7 @@
 	if (!elems.reconf_mle || !elems.reconf_mle_len)
 		return 0;
 
-	mlbuf = ieee802_11_defrag_mle(&elems, MULTI_LINK_CONTROL_TYPE_RECONF);
+	mlbuf = ieee802_11_defrag(elems.reconf_mle, elems.reconf_mle_len, true);
 	if (!mlbuf)
 		return 0;