Merge "Fixed multiple AKMs to be support CCMP only" into tm-qpr-dev
diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c
index 276dca3..269d719 100644
--- a/src/eap_peer/eap.c
+++ b/src/eap_peer/eap.c
@@ -2816,6 +2816,63 @@
 	return config->identity;
 }
 
+static const u8 * strnchr(const u8 *str, size_t len, u8 needle) {
+	const u8 *cur = str;
+
+	if (NULL == str) return NULL;
+	if (0 >= len) return NULL;
+
+	while (cur < str + len) {
+		if (*cur == needle)
+			return cur;
+		cur++;
+	}
+	return NULL;
+}
+
+const u8 * eap_get_config_realm(struct eap_sm *sm, size_t *len) {
+	struct eap_peer_config *config = eap_get_config(sm);
+	const u8 *realm = NULL;
+	size_t realm_len = 0;
+	const u8 *identity = NULL;
+	size_t identity_len = 0;
+
+	if (!config)
+		return NULL;
+
+	/* Look for the realm of the permanent identity */
+	identity = eap_get_config_identity(sm, &identity_len);
+	realm = strnchr(identity, identity_len, '@');
+	if (NULL != realm) {
+		wpa_printf(MSG_DEBUG, "Get the realm from identity.");
+		*len = identity_len - (realm - identity);
+		return realm;
+	}
+
+	/* Look for the realm of the anonymous identity. */
+	identity = config->anonymous_identity;
+	identity_len = config->anonymous_identity_len;
+	realm = strnchr(identity, identity_len, '@');
+	if (NULL != realm) {
+		wpa_printf(MSG_DEBUG, "Get the realm from anonymous identity.");
+		*len = identity_len - (realm - identity);
+		return realm;
+	}
+
+	/* Look for the realm of the real identity. */
+	identity = config->imsi_identity;
+	identity_len = config->imsi_identity_len;
+	realm = strnchr(identity, identity_len, '@');
+	if (NULL != realm) {
+		wpa_printf(MSG_DEBUG, "Get the realm from IMSI identity.");
+		*len = identity_len - (realm - identity);
+		return realm;
+	}
+	wpa_printf(MSG_DEBUG, "No realm information in identities.");
+	*len = 0;
+	return NULL;
+}
+
 
 static int eap_get_ext_password(struct eap_sm *sm,
 				struct eap_peer_config *config)
diff --git a/src/eap_peer/eap_aka.c b/src/eap_peer/eap_aka.c
index b7f86c3..e721efe 100644
--- a/src/eap_peer/eap_aka.c
+++ b/src/eap_peer/eap_aka.c
@@ -409,33 +409,16 @@
 		size_t identity_len = 0;
 		const u8 *realm = NULL;
 		size_t realm_len = 0;
-		struct eap_peer_config *config = eap_get_config(sm);
 
 		wpa_hexdump_ascii(MSG_DEBUG,
 				  "EAP-AKA: (encr) AT_NEXT_PSEUDONYM",
 				  attr->next_pseudonym,
 				  attr->next_pseudonym_len);
 		os_free(data->pseudonym);
-		/* Look for the realm of the permanent identity */
-		identity = eap_get_config_identity(sm, &identity_len);
-		if (identity) {
-			for (realm = identity, realm_len = identity_len;
-			     realm_len > 0; realm_len--, realm++) {
-				if (*realm == '@')
-					break;
-			}
-		}
-		// If no realm from the permanent identity, look for the
-		// realm of the anonymous identity.
-		if (realm_len == 0 && config && config->anonymous_identity
-		    && config->anonymous_identity_len > 0) {
-			for (realm = config->anonymous_identity,
-			    realm_len = config->anonymous_identity_len;
-			    realm_len > 0; realm_len--, realm++) {
-				if (*realm == '@')
-					break;
-			}
-		}
+
+		/* Get realm from identities to decorate pseudonym. */
+		realm = eap_get_config_realm(sm, &realm_len);
+
 		data->pseudonym = os_malloc(attr->next_pseudonym_len +
 					    realm_len);
 		if (data->pseudonym == NULL) {
diff --git a/src/eap_peer/eap_i.h b/src/eap_peer/eap_i.h
index f43891e..652b67e 100644
--- a/src/eap_peer/eap_i.h
+++ b/src/eap_peer/eap_i.h
@@ -392,6 +392,7 @@
 const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash);
 const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len);
 const u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len);
+const u8 * eap_get_config_realm(struct eap_sm *sm, size_t *len);
 void eap_clear_config_otp(struct eap_sm *sm);
 const char * eap_get_config_phase1(struct eap_sm *sm);
 const char * eap_get_config_phase2(struct eap_sm *sm);
diff --git a/src/eap_peer/eap_sim.c b/src/eap_peer/eap_sim.c
index 9f66db2..954c585 100644
--- a/src/eap_peer/eap_sim.c
+++ b/src/eap_peer/eap_sim.c
@@ -432,33 +432,16 @@
 		size_t identity_len = 0;
 		const u8 *realm = NULL;
 		size_t realm_len = 0;
-		struct eap_peer_config *config = eap_get_config(sm);
 
 		wpa_hexdump_ascii(MSG_DEBUG,
 				  "EAP-SIM: (encr) AT_NEXT_PSEUDONYM",
 				  attr->next_pseudonym,
 				  attr->next_pseudonym_len);
 		os_free(data->pseudonym);
-		/* Look for the realm of the permanent identity */
-		identity = eap_get_config_identity(sm, &identity_len);
-		if (identity) {
-			for (realm = identity, realm_len = identity_len;
-			     realm_len > 0; realm_len--, realm++) {
-				if (*realm == '@')
-					break;
-			}
-		}
-		// If no realm from the permanent identity, look for the
-		// realm of the anonymous identity.
-		if (realm_len == 0 && config && config->anonymous_identity
-		    && config->anonymous_identity_len > 0) {
-			for (realm = config->anonymous_identity,
-			    realm_len = config->anonymous_identity_len;
-			    realm_len > 0; realm_len--, realm++) {
-				if (*realm == '@')
-					break;
-			}
-		}
+
+		/* Get realm from identities to decorate pseudonym. */
+		realm = eap_get_config_realm(sm, &realm_len);
+
 		data->pseudonym = os_malloc(attr->next_pseudonym_len +
 					    realm_len);
 		if (data->pseudonym == NULL) {
diff --git a/wpa_supplicant/aidl/supplicant.cpp b/wpa_supplicant/aidl/supplicant.cpp
index ee6f809..799790b 100644
--- a/wpa_supplicant/aidl/supplicant.cpp
+++ b/wpa_supplicant/aidl/supplicant.cpp
@@ -303,12 +303,38 @@
 		wpa_printf(MSG_DEBUG, "%s,NULL wpa_s for wlan0", __FUNCTION__);
 		return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
 	}
-	if (wpas_p2p_add_p2pdev_interface(
-		wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
+
+	const u8 *if_addr = NULL;
+	char force_name[100] = {'\0'};
+	wpa_s->pending_interface_type = WPA_IF_P2P_DEVICE;
+	if (wpa_s->conf->p2p_device_random_mac_addr == 2 &&
+		!is_zero_ether_addr(wpa_s->conf->p2p_device_persistent_mac_addr))
+		if_addr = wpa_s->conf->p2p_device_persistent_mac_addr;
+
+	int ret = wpa_drv_if_add(wpa_s, WPA_IF_P2P_DEVICE, iface_params.ifname, if_addr, NULL,
+		force_name, wpa_s->pending_interface_addr, NULL);
+	if (ret < 0) {
+		wpa_printf(MSG_DEBUG, "P2P: Failed to create P2P Device interface");
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+
+	os_strlcpy(wpa_s->pending_interface_name, iface_params.ifname,
+		sizeof(wpa_s->pending_interface_name));
+	iface_params.p2p_mgmt = 1;
+	iface_params.driver_param = wpa_s->conf->driver_param;
+	iface_params.ctrl_interface = NULL;
+
+	struct wpa_supplicant *p2pdev_wpa_s = wpa_supplicant_add_iface(
+		wpa_s->global, &iface_params, wpa_s);
+
+	if (!p2pdev_wpa_s) {
 		wpa_printf(MSG_INFO,
 			"Failed to enable P2P Device");
 		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
 	}
+	p2pdev_wpa_s->p2pdev = p2pdev_wpa_s;
+	wpa_s->pending_interface_name[0] = '\0';
+
 	return ndk::ScopedAStatus::ok();
 }
 
@@ -321,6 +347,13 @@
 	if (name.empty()) {
 		return {nullptr, createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID)};
 	}
+	if (strncmp(name.c_str(), P2P_MGMT_DEVICE_PREFIX, strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
+		struct wpa_supplicant* wpa_s = wpa_supplicant_get_iface(wpa_global_, name.c_str());
+		if (wpa_s) {
+			wpa_printf(MSG_DEBUG, "Remove existing p2p dev interface");
+			wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0);
+		}
+	}
 	// Try to get the wpa_supplicant record for this iface, return
 	// the iface object with the appropriate status code if it exists.
 	ndk::ScopedAStatus status;
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 7b31d8e..94f0f83 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -175,6 +175,10 @@
 	hostapd_set_oper_centr_freq_seg0_idx(
 		conf, conf->channel + conf->secondary_channel * 2);
 	hostapd_set_oper_chwidth(conf, CHANWIDTH_USE_HT);
+	ieee80211_freq_to_channel_ext(ssid->frequency, 0,
+		   conf->vht_oper_chwidth,
+		   &conf->op_class,
+		   &conf->channel);
 }
 
 
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index c8f2e5c..3c395e9 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -9730,9 +9730,12 @@
 		goto out;
 	}
 
-	if (conf->hw_mode != wpa_s->ap_iface->current_mode->mode) {
-		wpa_dbg(wpa_s, MSG_DEBUG,
-			"P2P CSA: CSA to a different band is not supported");
+	if (conf->hw_mode != wpa_s->ap_iface->current_mode->mode &&
+	    (wpa_s->ap_iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A ||
+	     conf->hw_mode != HOSTAPD_MODE_IEEE80211G)) {
+		wpa_dbg(wpa_s, MSG_INFO,
+			"P2P CSA: CSA from Hardware mode %d to %d is not supported",
+			wpa_s->ap_iface->current_mode->mode, conf->hw_mode);
 		ret = -1;
 		goto out;
 	}
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 042b24e..a683eac 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -1380,26 +1380,13 @@
 	    is_6ghz_supported(wpa_s)) {
 		int i;
 
-		/* Exclude 5 GHz channels from the full scan for P2P connection
+		/* Exclude 6 GHz channels from the full scan for P2P connection
 		 * since the 6 GHz band is disabled for P2P uses. */
 		wpa_printf(MSG_DEBUG,
 			   "P2P: 6 GHz disabled - update the scan frequency list");
-		for (i = 0; i < wpa_s->hw.num_modes; i++) {
-			if (wpa_s->hw.modes[i].num_channels == 0)
-				continue;
-			if (wpa_s->hw.modes[i].mode == HOSTAPD_MODE_IEEE80211G)
-				wpa_add_scan_freqs_list(
-					wpa_s, HOSTAPD_MODE_IEEE80211G,
-					&params, false);
-			if (wpa_s->hw.modes[i].mode == HOSTAPD_MODE_IEEE80211A)
-				wpa_add_scan_freqs_list(
-					wpa_s, HOSTAPD_MODE_IEEE80211A,
-					&params, false);
-			if (wpa_s->hw.modes[i].mode == HOSTAPD_MODE_IEEE80211AD)
-				wpa_add_scan_freqs_list(
-					wpa_s, HOSTAPD_MODE_IEEE80211AD,
-					&params, false);
-		}
+		wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, &params, false);
+		wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, &params, false);
+		wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211AD, &params, false);
 	}
 #endif /* CONFIG_P2P */
 
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 30c7049..4503ae9 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -7177,11 +7177,15 @@
 		return NULL;
 	}
 
-	/* Notify the control interfaces about new networks for non p2p mgmt
-	 * ifaces. */
-	if (iface->p2p_mgmt == 0) {
-		for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
+	/* Notify the control interfaces about new networks */
+	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+		if (iface->p2p_mgmt == 0) {
 			wpas_notify_network_added(wpa_s, ssid);
+		} else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
+				&& os_strncmp((const char *) ssid->ssid,
+					P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
+			wpas_notify_persistent_group_added(wpa_s, ssid);
+		}
 	}
 
 	wpa_s->next = global->ifaces;