nl80211: Ignore Connect failure for the previous association

Suppose there are two APs (AP1 & AP2) and user attempted to connect to
AP2 before the previous connection with AP1 could succeed. Now, if the
connection event comes for the older AP with failed status, we should
just ignore it as the wpa_supplicant state has moved to "ASSOCIATING"
with the new AP (AP2).

This is a similar to the case where a disconnection event is ignored for
a case where local disconnect request can cause the extra event to show
up during the next association process following that command.

Signed-off-by: Jithu Jance <jithu@broadcom.com>
Signed-off-by: vandwalle <vandwalle@google.com>
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index d030474..4c8f29f 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -1591,6 +1591,7 @@
 			       struct nlattr *resp_ie)
 {
 	union wpa_event_data event;
+	u16 status_code;
 
 	if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
 		/*
@@ -1602,21 +1603,41 @@
 		return;
 	}
 
-	if (cmd == NL80211_CMD_CONNECT)
-		wpa_printf(MSG_DEBUG, "nl80211: Connect event");
-	else if (cmd == NL80211_CMD_ROAM)
+	status_code = status ? nla_get_u16(status) : WLAN_STATUS_SUCCESS;
+
+	if (cmd == NL80211_CMD_CONNECT) {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Connect event (status=%u ignore_next_local_disconnect=%d)",
+			   status_code, drv->ignore_next_local_disconnect);
+	} else if (cmd == NL80211_CMD_ROAM) {
 		wpa_printf(MSG_DEBUG, "nl80211: Roam event");
+	}
 
 	os_memset(&event, 0, sizeof(event));
-	if (cmd == NL80211_CMD_CONNECT &&
-	    nla_get_u16(status) != WLAN_STATUS_SUCCESS) {
+	if (cmd == NL80211_CMD_CONNECT && status_code != WLAN_STATUS_SUCCESS) {
 		if (addr)
 			event.assoc_reject.bssid = nla_data(addr);
+		if (drv->ignore_next_local_disconnect) {
+			drv->ignore_next_local_disconnect = 0;
+			if (!event.assoc_reject.bssid ||
+			    (os_memcmp(event.assoc_reject.bssid,
+				       drv->auth_attempt_bssid,
+				       ETH_ALEN) != 0)) {
+				/*
+				 * Ignore the event that came without a BSSID or
+				 * for the old connection since this is likely
+				 * not relevant to the new Connect command.
+				 */
+				wpa_printf(MSG_DEBUG,
+					   "nl80211: Ignore connection failure event triggered during reassociation");
+				return;
+			}
+		}
 		if (resp_ie) {
 			event.assoc_reject.resp_ies = nla_data(resp_ie);
 			event.assoc_reject.resp_ies_len = nla_len(resp_ie);
 		}
-		event.assoc_reject.status_code = nla_get_u16(status);
+		event.assoc_reject.status_code = status_code;
 		wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
 		return;
 	}
@@ -9086,7 +9107,15 @@
 	struct wpa_driver_nl80211_data *drv,
 	struct wpa_driver_associate_params *params)
 {
-	int ret = wpa_driver_nl80211_try_connect(drv, params);
+	int ret;
+
+	/* Store the connection attempted bssid for future use */
+	if (params->bssid)
+		os_memcpy(drv->auth_attempt_bssid, params->bssid, ETH_ALEN);
+	else
+		os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
+
+	ret = wpa_driver_nl80211_try_connect(drv, params);
 	if (ret == -EALREADY) {
 		/*
 		 * cfg80211 does not currently accept new connections if