Merge "wifi: implement enable SAE PK only mode API"
diff --git a/hostapd/hidl/1.3/hostapd.cpp b/hostapd/hidl/1.3/hostapd.cpp
index ee3a44e..6450a9f 100644
--- a/hostapd/hidl/1.3/hostapd.cpp
+++ b/hostapd/hidl/1.3/hostapd.cpp
@@ -10,9 +10,14 @@
 #include <sstream>
 #include <string>
 #include <vector>
+#include <net/if.h>
+#include <sys/socket.h>
+#include <linux/if_bridge.h>
+
 
 #include <android-base/file.h>
 #include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
 
 #include "hostapd.h"
 #include "hidl_return_util.h"
@@ -20,6 +25,7 @@
 extern "C"
 {
 #include "common/wpa_ctrl.h"
+#include "drivers/linux_ioctl.h"
 }
 
 // The HIDL implementation for hostapd creates a hostapd.conf dynamically for
@@ -37,6 +43,46 @@
 using android::hardware::wifi::hostapd::V1_3::Generation;
 using android::hardware::wifi::hostapd::V1_3::Bandwidth;
 
+#define MAX_PORTS 1024
+bool GetInterfacesInBridge(std::string br_name,
+                           std::vector<std::string>* interfaces) {
+	android::base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
+	if (sock.get() < 0) {
+		wpa_printf(MSG_ERROR, "Failed to create sock (%s) in %s",
+			strerror(errno), __FUNCTION__);
+		return false;
+	}
+
+	struct ifreq request;
+	int i, ifindices[MAX_PORTS];
+	char if_name[IFNAMSIZ];
+	unsigned long args[3];
+
+	memset(ifindices, 0, MAX_PORTS * sizeof(int));
+
+	args[0] = BRCTL_GET_PORT_LIST;
+	args[1] = (unsigned long) ifindices;
+	args[2] = MAX_PORTS;
+
+	strlcpy(request.ifr_name, br_name.c_str(), IFNAMSIZ);
+	request.ifr_data = (char *)args;
+
+	if (ioctl(sock.get(), SIOCDEVPRIVATE, &request) < 0) {
+		wpa_printf(MSG_ERROR, "Failed to ioctl SIOCDEVPRIVATE in %s",
+			__FUNCTION__);
+		return false;
+	}
+
+	for (i = 0; i < MAX_PORTS; i ++) {
+		memset(if_name, 0, IFNAMSIZ);
+		if (ifindices[i] == 0 || !if_indextoname(ifindices[i], if_name)) {
+			continue;
+		}
+		interfaces->push_back(if_name);
+	}
+	return true;
+}
+
 std::string WriteHostapdConfig(
     const std::string& interface_name, const std::string& config)
 {
@@ -217,8 +263,9 @@
 }
 
 std::string CreateHostapdConfig(
-    const IHostapd::IfaceParams& iface_params,
-    const IHostapd::NetworkParams& nw_params)
+    const android::hardware::wifi::hostapd::V1_2::IHostapd::IfaceParams& iface_params,
+    const IHostapd::NetworkParams& nw_params,
+    const std::string br_name)
 {
 	if (nw_params.V1_2.V1_0.ssid.size() >
 	    static_cast<uint32_t>(
@@ -412,6 +459,11 @@
 	}
 #endif /* CONFIG_INTERWORKING */
 
+	std::string bridge_as_string;
+	if (!br_name.empty()) {
+		bridge_as_string = StringPrintf("bridge=%s", br_name.c_str());
+	}
+
 	return StringPrintf(
 	    "interface=%s\n"
 	    "driver=nl80211\n"
@@ -431,6 +483,7 @@
 #ifdef CONFIG_INTERWORKING
 	    "%s\n"
 #endif /* CONFIG_INTERWORKING */
+	    "%s\n"
 	    "%s\n",
 	    iface_params.V1_1.V1_0.ifaceName.c_str(), ssid_as_string.c_str(),
 	    channel_config_as_string.c_str(),
@@ -440,9 +493,10 @@
 	    hw_mode_as_string.c_str(), ht_cap_vht_oper_chwidth_as_string.c_str(),
 	    nw_params.V1_2.V1_0.isHidden ? 1 : 0,
 #ifdef CONFIG_INTERWORKING
-            access_network_params_as_string.c_str(),
+	    access_network_params_as_string.c_str(),
 #endif /* CONFIG_INTERWORKING */
-            encryption_config_as_string.c_str());
+	    encryption_config_as_string.c_str(),
+	    bridge_as_string.c_str());
 }
 
 Generation getGeneration(hostapd_hw_modes *current_mode)
@@ -504,8 +558,10 @@
 	if (on_setup_complete_internal_callback) {
 		on_setup_complete_internal_callback(iface_hapd);
 		// Invalidate this callback since we don't want this firing
-		// again.
-		on_setup_complete_internal_callback = nullptr;
+		// again in single AP mode.
+		if (strlen(iface_hapd->conf->bridge) > 0) {
+		    on_setup_complete_internal_callback = nullptr;
+		}
 	}
 }
 
@@ -655,17 +711,89 @@
 	return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
 }
 
+V1_2::IHostapd::IfaceParams prepareIfaceParams1_2From1_3(const std::string interfaceName,
+	const V1_3::IHostapd::IfaceParams iface_1_3,
+	const V1_3::IHostapd::ChannelParams channelParams_1_3)
+{
+	// Using HIDL 1.2 iface_params to enable the AP
+	V1_2::IHostapd::IfaceParams iface_params_1_2 = iface_1_3.V1_2;
+	iface_params_1_2.V1_1.V1_0.ifaceName = interfaceName;
+	// Prepare bandMask & acsChannelFreqRangesMhz
+	iface_params_1_2.channelParams = channelParams_1_3.V1_2;
+	// Prepare channel
+	iface_params_1_2.V1_1.V1_0.channelParams.channel = channelParams_1_3.channel;
+	// Prepare enableAcs
+	iface_params_1_2.V1_1.V1_0.channelParams.enableAcs = channelParams_1_3.enableAcs;
+	return iface_params_1_2;
+}
+
 V1_2::HostapdStatus Hostapd::addAccessPointInternal_1_3(
-    const V1_2::IHostapd::IfaceParams& iface_params,
+    const V1_3::IHostapd::IfaceParams& iface_params,
     const V1_3::IHostapd::NetworkParams& nw_params)
 {
+	int channelParamsListSize = iface_params.channelParamsList.size();
+	if (channelParamsListSize == 1) {
+		// Single AP
+		wpa_printf(MSG_INFO, "AddSingleAccessPoint, iface=%s",
+		    iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
+		return addSingleAccessPoint(
+		    prepareIfaceParams1_2From1_3(iface_params.V1_2.V1_1.V1_0.ifaceName,
+						 iface_params, iface_params.channelParamsList[0]),
+		    nw_params, "");
+	} else if (channelParamsListSize == 2) {
+		// Concurrent APs
+		wpa_printf(MSG_INFO, "AddDualAccessPoint, iface=%s",
+		    iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
+		return addConcurrentAccessPoints(iface_params, nw_params);
+	}
+	return {V1_2::HostapdStatusCode::FAILURE_ARGS_INVALID, ""};
+}
+
+V1_2::HostapdStatus Hostapd::addConcurrentAccessPoints(
+    const V1_3::IHostapd::IfaceParams& iface_params, const V1_3::IHostapd::NetworkParams& nw_params)
+{
+	int channelParamsListSize = iface_params.channelParamsList.size();
+	// Get available interfaces in bridge
+	std::vector<std::string> managed_interfaces;
+	std::string br_name = StringPrintf(
+	    "%s", iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
+	if (!GetInterfacesInBridge(br_name, &managed_interfaces)) {
+		return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN,
+		    "Get interfaces in bridge failed."};
+	}
+	if (managed_interfaces.size() < channelParamsListSize) {
+		return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN,
+		    "Available interfaces less than requested bands"};
+	}
+	// start BSS on specified bands
+	for (std::size_t i = 0; i < channelParamsListSize; i ++) {
+		V1_2::HostapdStatus status = addSingleAccessPoint(
+		    prepareIfaceParams1_2From1_3(managed_interfaces[i], iface_params,
+						 iface_params.channelParamsList[i]),
+		    nw_params, br_name);
+		if (status.code != V1_2::HostapdStatusCode::SUCCESS) {
+			wpa_printf(MSG_ERROR, "Failed to addAccessPoint %s",
+				   managed_interfaces[i].c_str());
+			return status;
+		}
+	}
+	// Save bridge interface info
+	br_interfaces_[br_name] = managed_interfaces;
+	return {V1_2::HostapdStatusCode::SUCCESS, ""};
+}
+
+V1_2::HostapdStatus Hostapd::addSingleAccessPoint(
+    const V1_2::IHostapd::IfaceParams& iface_params,
+    const V1_3::IHostapd::NetworkParams& nw_params,
+    const std::string br_name)
+{
 	if (hostapd_get_iface(interfaces_, iface_params.V1_1.V1_0.ifaceName.c_str())) {
 		wpa_printf(
 		    MSG_ERROR, "Interface %s already present",
 		    iface_params.V1_1.V1_0.ifaceName.c_str());
 		return {V1_2::HostapdStatusCode::FAILURE_IFACE_EXISTS, ""};
 	}
-	const auto conf_params = CreateHostapdConfig(iface_params, nw_params);
+	const auto conf_params = CreateHostapdConfig(iface_params, nw_params, br_name);
 	if (conf_params.empty()) {
 		wpa_printf(MSG_ERROR, "Failed to create config params");
 		return {V1_2::HostapdStatusCode::FAILURE_ARGS_INVALID, ""};
@@ -694,7 +822,7 @@
 	on_setup_complete_internal_callback =
 	    [this](struct hostapd_data* iface_hapd) {
 		    wpa_printf(
-			MSG_DEBUG, "AP interface setup completed - state %s",
+			MSG_INFO, "AP interface setup completed - state %s",
 			hostapd_state_text(iface_hapd->iface->state));
 		    if (iface_hapd->iface->state == HAPD_IFACE_DISABLED) {
 			    // Invoke the failure callback on all registered
@@ -713,11 +841,9 @@
 		wpa_printf(MSG_DEBUG, "notify client " MACSTR " %s",
 			   MAC2STR(mac_addr),
 			   (authorized) ? "Connected" : "Disconnected");
-
 		for (const auto &callback : callbacks_) {
-		    // TODO: The iface need to separate to iface and ap instance
-		    // identify for AP+AP case.
-		    callback->onConnectedClientsChanged(iface_hapd->conf->iface,
+		    callback->onConnectedClientsChanged(strlen(iface_hapd->conf->bridge) > 0 ?
+			    iface_hapd->conf->bridge : iface_hapd->conf->iface,
 			    iface_hapd->conf->iface, mac_addr, authorized);
 		}
 	    };
@@ -732,8 +858,10 @@
 			       strlen(WPA_EVENT_CHANNEL_SWITCH)) == 0) {
 		    for (const auto &callback : callbacks_) {
 			callback->onApInstanceInfoChanged(
-				iface_hapd->conf->iface, iface_hapd->conf->iface,
-				iface_hapd->iface->freq, getBandwidth(iface_hapd->iconf),
+				strlen(iface_hapd->conf->bridge) > 0 ?
+				iface_hapd->conf->bridge : iface_hapd->conf->iface,
+				iface_hapd->conf->iface, iface_hapd->iface->freq,
+				getBandwidth(iface_hapd->iconf),
 				getGeneration(iface_hapd->iface->current_mode),
 				iface_hapd->own_addr);
 		    }
diff --git a/hostapd/hidl/1.3/hostapd.h b/hostapd/hidl/1.3/hostapd.h
index 79354d3..ceec080 100644
--- a/hostapd/hidl/1.3/hostapd.h
+++ b/hostapd/hidl/1.3/hostapd.h
@@ -71,7 +71,7 @@
 	    const V1_2::IHostapd::NetworkParams& nw_params,
 	    addAccessPoint_1_2_cb _hidl_cb) override;
 	Return<void> addAccessPoint_1_3(
-	    const V1_2::IHostapd::IfaceParams& iface_params,
+	    const V1_3::IHostapd::IfaceParams& iface_params,
 	    const V1_3::IHostapd::NetworkParams& nw_params,
 	    addAccessPoint_1_3_cb _hidl_cb) override;
 	Return<void> removeAccessPoint(
@@ -102,7 +102,14 @@
 	    const V1_2::IHostapd::IfaceParams& IfaceParams,
 	    const V1_2::IHostapd::NetworkParams& nw_params);
 	V1_2::HostapdStatus addAccessPointInternal_1_3(
+	    const V1_3::IHostapd::IfaceParams& IfaceParams,
+	    const V1_3::IHostapd::NetworkParams& nw_params);
+	V1_2::HostapdStatus addSingleAccessPoint(
 	    const V1_2::IHostapd::IfaceParams& IfaceParams,
+	    const V1_3::IHostapd::NetworkParams& nw_params,
+	    std::string br_name);
+	V1_2::HostapdStatus addConcurrentAccessPoints(
+	    const V1_3::IHostapd::IfaceParams& IfaceParams,
 	    const V1_3::IHostapd::NetworkParams& nw_params);
 	V1_0::HostapdStatus removeAccessPointInternal(const std::string& iface_name);
 	V1_0::HostapdStatus registerCallbackInternal(
@@ -120,6 +127,8 @@
 	std::vector<sp<V1_3::IHostapdCallback>> callbacks_;
 	// Death notifier.
 	android::sp<DeathNotifier> death_notifier_;
+	// Bridge and its managed interfaces.
+	std::map<std::string, std::vector<std::string>> br_interfaces_;
 	DISALLOW_COPY_AND_ASSIGN(Hostapd);
 };
 }  // namespace implementation
diff --git a/src/utils/list.h b/src/utils/list.h
index 85aa5e3..5298c26 100644
--- a/src/utils/list.h
+++ b/src/utils/list.h
@@ -46,12 +46,12 @@
 	item->prev = NULL;
 }
 
-static inline int dl_list_empty(struct dl_list *list)
+static inline int dl_list_empty(const struct dl_list *list)
 {
 	return list->next == list;
 }
 
-static inline unsigned int dl_list_len(struct dl_list *list)
+static inline unsigned int dl_list_len(const struct dl_list *list)
 {
 	struct dl_list *item;
 	int count = 0;
diff --git a/wpa_supplicant/hidl/1.4/hidl_manager.cpp b/wpa_supplicant/hidl/1.4/hidl_manager.cpp
index d7136a6..8325311 100644
--- a/wpa_supplicant/hidl/1.4/hidl_manager.cpp
+++ b/wpa_supplicant/hidl/1.4/hidl_manager.cpp
@@ -17,6 +17,7 @@
 extern "C" {
 #include "scan.h"
 #include "src/eap_common/eap_sim_common.h"
+#include "list.h"
 }
 
 namespace {
@@ -821,23 +822,33 @@
 	    sta_iface_object_map_.end())
 		return;
 
-	ISupplicantStaIfaceCallback::AnqpData hidl_anqp_data;
+	V1_4::ISupplicantStaIfaceCallback::AnqpData hidl_anqp_data;
 	ISupplicantStaIfaceCallback::Hs20AnqpData hidl_hs20_anqp_data;
 	if (std::string(result) == "SUCCESS") {
-		hidl_anqp_data.venueName =
+		hidl_anqp_data.V1_0.venueName =
 		    misc_utils::convertWpaBufToVector(anqp->venue_name);
-		hidl_anqp_data.roamingConsortium =
+		hidl_anqp_data.V1_0.roamingConsortium =
 		    misc_utils::convertWpaBufToVector(anqp->roaming_consortium);
-		hidl_anqp_data.ipAddrTypeAvailability =
+		hidl_anqp_data.V1_0.ipAddrTypeAvailability =
 		    misc_utils::convertWpaBufToVector(
 			anqp->ip_addr_type_availability);
-		hidl_anqp_data.naiRealm =
+		hidl_anqp_data.V1_0.naiRealm =
 		    misc_utils::convertWpaBufToVector(anqp->nai_realm);
-		hidl_anqp_data.anqp3gppCellularNetwork =
+		hidl_anqp_data.V1_0.anqp3gppCellularNetwork =
 		    misc_utils::convertWpaBufToVector(anqp->anqp_3gpp);
-		hidl_anqp_data.domainName =
+		hidl_anqp_data.V1_0.domainName =
 		    misc_utils::convertWpaBufToVector(anqp->domain_name);
 
+		struct wpa_bss_anqp_elem *elem;
+		dl_list_for_each(elem, &anqp->anqp_elems, struct wpa_bss_anqp_elem,
+				 list) {
+			if (elem->infoid == ANQP_VENUE_URL) {
+				hidl_anqp_data.venueUrl =
+						    misc_utils::convertWpaBufToVector(elem->payload);
+				break;
+			}
+		}
+
 		hidl_hs20_anqp_data.operatorFriendlyName =
 		    misc_utils::convertWpaBufToVector(
 			anqp->hs20_operator_friendly_name);
@@ -851,9 +862,9 @@
 			anqp->hs20_osu_providers_list);
 	}
 
-	callWithEachStaIfaceCallback(
+	callWithEachStaIfaceCallback_1_4(
 	    wpa_s->ifname, std::bind(
-			       &ISupplicantStaIfaceCallback::onAnqpQueryDone,
+			       &V1_4::ISupplicantStaIfaceCallback::onAnqpQueryDone_1_4,
 			       std::placeholders::_1, bssid, hidl_anqp_data,
 			       hidl_hs20_anqp_data));
 }
diff --git a/wpa_supplicant/hidl/1.4/hidl_manager.h b/wpa_supplicant/hidl/1.4/hidl_manager.h
index e3d6312..f027676 100644
--- a/wpa_supplicant/hidl/1.4/hidl_manager.h
+++ b/wpa_supplicant/hidl/1.4/hidl_manager.h
@@ -16,7 +16,7 @@
 #include <android/hardware/wifi/supplicant/1.0/ISupplicantCallback.h>
 #include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pIfaceCallback.h>
 #include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pNetworkCallback.h>
-#include <android/hardware/wifi/supplicant/1.0/ISupplicantStaIfaceCallback.h>
+#include <android/hardware/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.h>
 #include <android/hardware/wifi/supplicant/1.0/ISupplicantStaNetworkCallback.h>
 #include <android/hardware/wifi/supplicant/1.4/ISupplicantStaNetworkCallback.h>
 
diff --git a/wpa_supplicant/hidl/1.4/sta_iface.cpp b/wpa_supplicant/hidl/1.4/sta_iface.cpp
index 7ba9cd8..1684382 100644
--- a/wpa_supplicant/hidl/1.4/sta_iface.cpp
+++ b/wpa_supplicant/hidl/1.4/sta_iface.cpp
@@ -402,7 +402,7 @@
 }
 Return<void> StaIface::initiateAnqpQuery(
     const hidl_array<uint8_t, 6> &mac_address,
-    const hidl_vec<ISupplicantStaIface::AnqpInfoId> &info_elements,
+    const hidl_vec<V1_0::ISupplicantStaIface::AnqpInfoId> &info_elements,
     const hidl_vec<ISupplicantStaIface::Hs20AnqpSubtypes> &sub_types,
     initiateAnqpQuery_cb _hidl_cb)
 {
@@ -412,6 +412,15 @@
 	    info_elements, sub_types);
 }
 
+Return<void> StaIface::initiateVenueUrlAnqpQuery(
+    const hidl_array<uint8_t, 6> &mac_address,
+	initiateVenueUrlAnqpQuery_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, V1_4::SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::initiateVenueUrlAnqpQueryInternal, _hidl_cb, mac_address);
+}
+
 Return<void> StaIface::initiateHs20IconQuery(
     const hidl_array<uint8_t, 6> &mac_address, const hidl_string &file_name,
     initiateHs20IconQuery_cb _hidl_cb)
@@ -986,6 +995,19 @@
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
 
+V1_4::SupplicantStatus StaIface::initiateVenueUrlAnqpQueryInternal(
+    const std::array<uint8_t, 6> &mac_address)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	uint16_t info_elems_buf[1] = {ANQP_VENUE_URL};
+
+	if (anqp_send_req(
+		wpa_s, mac_address.data(), 0, info_elems_buf, 1, 0, 0)) {
+		return {V1_4::SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
+}
+
 SupplicantStatus StaIface::initiateHs20IconQueryInternal(
     const std::array<uint8_t, 6> &mac_address, const std::string &file_name)
 {
diff --git a/wpa_supplicant/hidl/1.4/sta_iface.h b/wpa_supplicant/hidl/1.4/sta_iface.h
index bf20b28..bb5344b 100644
--- a/wpa_supplicant/hidl/1.4/sta_iface.h
+++ b/wpa_supplicant/hidl/1.4/sta_iface.h
@@ -109,9 +109,12 @@
 	    initiateTdlsTeardown_cb _hidl_cb) override;
 	Return<void> initiateAnqpQuery(
 	    const hidl_array<uint8_t, 6>& mac_address,
-	    const hidl_vec<ISupplicantStaIface::AnqpInfoId>& info_elements,
+	    const hidl_vec<V1_0::ISupplicantStaIface::AnqpInfoId>& info_elements,
 	    const hidl_vec<ISupplicantStaIface::Hs20AnqpSubtypes>& sub_types,
 	    initiateAnqpQuery_cb _hidl_cb) override;
+	Return<void> initiateVenueUrlAnqpQuery(
+	    const hidl_array<uint8_t, 6>& mac_address,
+		initiateVenueUrlAnqpQuery_cb _hidl_cb) override;
 	Return<void> initiateHs20IconQuery(
 	    const hidl_array<uint8_t, 6>& mac_address,
 	    const hidl_string& file_name,
@@ -239,6 +242,8 @@
 	    const std::vector<ISupplicantStaIface::AnqpInfoId>& info_elements,
 	    const std::vector<ISupplicantStaIface::Hs20AnqpSubtypes>&
 		sub_types);
+	V1_4::SupplicantStatus initiateVenueUrlAnqpQueryInternal(
+	    const std::array<uint8_t, 6>& mac_address);
 	SupplicantStatus initiateHs20IconQueryInternal(
 	    const std::array<uint8_t, 6>& mac_address,
 	    const std::string& file_name);
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index c799b5a..3946252 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -2998,13 +2998,13 @@
 	case ANQP_VENUE_URL:
 		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR " Venue URL",
 			MAC2STR(sa));
-		anqp_add_extra(wpa_s, anqp, info_id, pos, slen);
 
 		if (!pmf_in_use(wpa_s, sa)) {
 			wpa_printf(MSG_DEBUG,
 				   "ANQP: Ignore Venue URL since PMF was not enabled");
 			break;
 		}
+		anqp_add_extra(wpa_s, anqp, info_id, pos, slen);
 		interworking_parse_venue_url(wpa_s, pos, slen);
 		break;
 	case ANQP_VENDOR_SPECIFIC:
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 67fb426..6ab5485 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3844,6 +3844,8 @@
 			 * succeed.
 			 */
 			wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
+			wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
+			wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0);
 			wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
 			os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
 			return;