Patchwork SCAN: Fix unexpected disconnection in re-scheduled STA scan during P2P concurrent operation.

login
register
mail settings
Submitter Poulain, LoicX
Date June 3, 2013, 10:22 a.m.
Message ID <4ED7A9645AB51849A442949141BBE1F5C68136@IRSMSX102.ger.corp.intel.com>
Download mbox | patch
Permalink /patch/248223/
State Accepted
Headers show

Comments

Poulain, LoicX - June 3, 2013, 10:22 a.m.
Hello Jouni, list,

I have  noticed an issue in scan results processing.
Indeed, on scan results event if a concurrent p2p scan was triggered
previously, scan results processing is canceled, p2p_find
executed and a new STA scan is triggered (pending scan).

However this new STA scan does not restore the scan_req value
of the previous scan (whose scan result has been canceled).
If we are currently AP connected, the new triggered scan will
cause an assoc whereas we are already connected.
This mechanism can cause an unexpected disconnection.
Jouni Malinen - Nov. 24, 2013, 11:27 a.m.
On Mon, Jun 03, 2013 at 10:22:25AM +0000, Poulain, LoicX wrote:
> I have  noticed an issue in scan results processing.
> Indeed, on scan results event if a concurrent p2p scan was triggered
> previously, scan results processing is canceled, p2p_find
> executed and a new STA scan is triggered (pending scan).
> 
> However this new STA scan does not restore the scan_req value
> of the previous scan (whose scan result has been canceled).
> If we are currently AP connected, the new triggered scan will
> cause an assoc whereas we are already connected.
> This mechanism can cause an unexpected disconnection.

Thanks, applied.

Patch

From 7feb3f6674e0ba2eb145c5d60730942a882f47ba Mon Sep 17 00:00:00 2001
From: Loic Poulain <loicx.poulain@intel.com>
Date: Fri, 31 May 2013 12:15:56 +0200
Subject: [PATCH] Restore scan_req value if a sta scan is rescheduled in the scan results event

On scan results event if a concurrent p2p scan was triggered previously,
scan results processing is canceled, p2p_find executed and a new sta scan is
triggered (pending scan).

However this new sta scan does not restore the scan_req value of the previous
scan (whose scan result has been canceled).

If we are currently ap connected, the new triggered scan will cause an assoc
whereas we are already connected:
(ap_scan==2 & scan_req!= scan_req != MANUAL_SCAN_REQ)
	=> wpa_supplicant_assoc_try()
causing an assoc error and a disconnection.

This patch fixes this issue by restoring the previous scan_req value.

Signed-off-by: Loic Poulain <loicx.poulain@intel.com>
---
 wpa_supplicant/events.c           |    1 +
 wpa_supplicant/scan.c             |   14 ++++++++------
 wpa_supplicant/wpa_supplicant_i.h |    2 +-
 3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 50a0dbd..6bbbd6a 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1122,6 +1122,7 @@  static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
 		if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) {
 			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation "
 				"stopped scan processing");
+			wpa_s->scan_req = wpa_s->last_scan_req;
 			wpa_s->sta_scan_pending = 1;
 			wpa_supplicant_req_scan(wpa_s, 5, 0);
 			return -1;
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index bdd6815..f8eafde 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -583,7 +583,6 @@  static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
 {
 	struct wpa_supplicant *wpa_s = eloop_ctx;
 	struct wpa_ssid *ssid;
-	enum scan_req_type scan_req = NORMAL_SCAN_REQ;
 	int ret;
 	struct wpabuf *extra_ie = NULL;
 	struct wpa_driver_scan_params params;
@@ -650,7 +649,7 @@  static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
 			max_ssids = WPAS_MAX_SCAN_SSIDS;
 	}
 
-	scan_req = wpa_s->scan_req;
+	wpa_s->last_scan_req = wpa_s->scan_req;
 	wpa_s->scan_req = NORMAL_SCAN_REQ;
 
 	os_memset(&params, 0, sizeof(params));
@@ -668,7 +667,8 @@  static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
 		goto scan;
 	}
 
-	if (scan_req != MANUAL_SCAN_REQ && wpa_s->connect_without_scan) {
+	if (wpa_s->last_scan_req != MANUAL_SCAN_REQ &&
+	    wpa_s->connect_without_scan) {
 		for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
 			if (ssid == wpa_s->connect_without_scan)
 				break;
@@ -706,7 +706,8 @@  static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
 		}
 	}
 
-	if (scan_req != MANUAL_SCAN_REQ && wpa_s->conf->ap_scan == 2) {
+	if (wpa_s->last_scan_req != MANUAL_SCAN_REQ &&
+	    wpa_s->conf->ap_scan == 2) {
 		wpa_s->connect_without_scan = NULL;
 		wpa_s->prev_scan_wildcard = 0;
 		wpa_supplicant_assoc_try(wpa_s, ssid);
@@ -857,7 +858,8 @@  scan:
 	 * station interface when we are not configured to prefer station
 	 * connection and a concurrent operation is already in process.
 	 */
-	if (wpa_s->scan_for_connection && scan_req == NORMAL_SCAN_REQ &&
+	if (wpa_s->scan_for_connection &&
+	    wpa_s->last_scan_req == NORMAL_SCAN_REQ &&
 	    !scan_params->freqs && !params.freqs &&
 	    wpas_is_p2p_prioritized(wpa_s) &&
 	    !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT) &&
@@ -887,7 +889,7 @@  scan:
 		if (prev_state != wpa_s->wpa_state)
 			wpa_supplicant_set_state(wpa_s, prev_state);
 		/* Restore scan_req since we will try to scan again */
-		wpa_s->scan_req = scan_req;
+		wpa_s->scan_req = wpa_s->last_scan_req;
 		wpa_supplicant_req_scan(wpa_s, 1, 0);
 	} else {
 		wpa_s->scan_for_connection = 0;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index c971ae4..bc7ec98 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -459,7 +459,7 @@  struct wpa_supplicant {
 		 * to be run.
 		 */
 		MANUAL_SCAN_REQ
-	} scan_req;
+	} scan_req, last_scan_req;
 	struct os_time scan_trigger_time;
 	int scan_runs; /* number of scan runs since WPS was started */
 	int *next_scan_freqs;
-- 
1.7.0.4