Cumulative patch from commit 06c7b7f0b5f4deed675a7b81e33830311da7339a

06c7b7f HS 2.0R2: Fix temporary network disabling in Deauth Req case
c5c2d94 P2P: Cancel offchannel TX wait on PD Response TX status
1578796 TDLS: Work around interop issues with supported operating class
b7fb98f Interworking: Fix already-connected check to verify network priority
7c373ac Interworking: Fix last-network preference to not override priority
f54e924 HS 2.0R2: Fix req_conn_capab example

Change-Id: I17953fc05421bc5d454f4081fbfe303f4bf2d6fd
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 6f3cd68..4b90989 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -2990,6 +2990,10 @@
 	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
 	switch (state) {
 	case P2P_NO_PENDING_ACTION:
+		if (p2p->send_action_in_progress) {
+			p2p->send_action_in_progress = 0;
+			p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
+		}
 		if (p2p->after_scan_tx_in_progress) {
 			p2p->after_scan_tx_in_progress = 0;
 			if (p2p->start_after_scan != P2P_AFTER_SCAN_NOTHING &&
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index 6de3461..420c739 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -389,6 +389,7 @@
 	u8 after_scan_peer[ETH_ALEN];
 	struct p2p_pending_action_tx *after_scan_tx;
 	unsigned int after_scan_tx_in_progress:1;
+	unsigned int send_action_in_progress:1;
 
 	/* Requested device types for find/search */
 	unsigned int num_req_dev_types;
diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c
index 409405f..68d79d2 100644
--- a/src/p2p/p2p_pd.c
+++ b/src/p2p/p2p_pd.c
@@ -224,7 +224,8 @@
 			    p2p->cfg->dev_addr,
 			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
 		p2p_dbg(p2p, "Failed to send Action frame");
-	}
+	} else
+		p2p->send_action_in_progress = 1;
 
 	wpabuf_free(resp);
 
diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c
index 9c11183..610b65a 100644
--- a/src/rsn_supp/wpa_ie.c
+++ b/src/rsn_supp/wpa_ie.c
@@ -522,8 +522,16 @@
 			ie->supp_channels = pos + 2;
 			ie->supp_channels_len = pos[1];
 		} else if (*pos == WLAN_EID_SUPPORTED_OPERATING_CLASSES) {
-			ie->supp_oper_classes = pos + 2;
-			ie->supp_oper_classes_len = pos[1];
+			/*
+			 * The value of the Length field of the Supported
+			 * Operating Classes element is between 2 and 253.
+			 * Silently skip invalid elements to avoid interop
+			 * issues when trying to use the value.
+			 */
+			if (pos[1] >= 2 && pos[1] <= 253) {
+				ie->supp_oper_classes = pos + 2;
+				ie->supp_oper_classes_len = pos[1];
+			}
 		} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
 			ret = wpa_parse_generic(pos, end, ie);
 			if (ret < 0)
diff --git a/wpa_supplicant/README-HS20 b/wpa_supplicant/README-HS20
index b6f0673..d0b0b50 100644
--- a/wpa_supplicant/README-HS20
+++ b/wpa_supplicant/README-HS20
@@ -260,7 +260,7 @@
 #	Format: <protocol>[:<comma-separated list of ports]
 #	Multiple entries can be used to list multiple requirements.
 #	For example, number of common TCP protocols:
-#	req_conn_capab=6,22,80,443
+#	req_conn_capab=6:22,80,443
 #	For example, IPSec/IKE:
 #	req_conn_capab=17:500
 #	req_conn_capab=50
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index c0f55ee..bea7f8a 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -993,30 +993,33 @@
 {
 	struct wpa_bss *selected = NULL;
 	int prio;
+	struct wpa_ssid *next_ssid = NULL;
 
 	if (wpa_s->last_scan_res == NULL ||
 	    wpa_s->last_scan_res_used == 0)
 		return NULL; /* no scan results from last update */
 
+	if (wpa_s->next_ssid) {
+		struct wpa_ssid *ssid;
+
+		/* check that next_ssid is still valid */
+		for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+			if (ssid == wpa_s->next_ssid)
+				break;
+		}
+		next_ssid = ssid;
+		wpa_s->next_ssid = NULL;
+	}
+
 	while (selected == NULL) {
-		if (wpa_s->next_ssid) {
-			struct wpa_ssid *ssid;
-
-			/* check that next_ssid is still valid */
-			for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
-				if (ssid == wpa_s->next_ssid)
-					break;
-			wpa_s->next_ssid = NULL;
-
-			if (ssid) {
+		for (prio = 0; prio < wpa_s->conf->num_prio; prio++) {
+			if (next_ssid && next_ssid->priority ==
+			    wpa_s->conf->pssid[prio]->priority) {
 				selected = wpa_supplicant_select_bss(
-					wpa_s, ssid, selected_ssid, 1);
+					wpa_s, next_ssid, selected_ssid, 1);
 				if (selected)
 					break;
 			}
-		}
-
-		for (prio = 0; prio < wpa_s->conf->num_prio; prio++) {
 			selected = wpa_supplicant_select_bss(
 				wpa_s, wpa_s->conf->pssid[prio],
 				selected_ssid, 0);
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index b873c7c..b342d5d 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -885,8 +885,8 @@
 		/* TODO: For now, disable full ESS since some drivers may not
 		 * support disabling per BSS. */
 		if (wpa_s->current_ssid) {
-			struct os_time now;
-			os_get_time(&now);
+			struct os_reltime now;
+			os_get_reltime(&now);
 			if (now.sec + reauth_delay <=
 			    wpa_s->current_ssid->disabled_until.sec)
 				return;
@@ -898,8 +898,8 @@
 	}
 
 	if (code == HS20_DEAUTH_REASON_CODE_ESS && wpa_s->current_ssid) {
-		struct os_time now;
-		os_get_time(&now);
+		struct os_reltime now;
+		os_get_reltime(&now);
 		if (now.sec + reauth_delay <=
 		    wpa_s->current_ssid->disabled_until.sec)
 			return;
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index abf5dee..42fefb6 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -814,7 +814,8 @@
 static int already_connected(struct wpa_supplicant *wpa_s,
 			     struct wpa_cred *cred, struct wpa_bss *bss)
 {
-	struct wpa_ssid *ssid;
+	struct wpa_ssid *ssid, *sel_ssid;
+	struct wpa_bss *selected;
 
 	if (wpa_s->wpa_state < WPA_ASSOCIATED || wpa_s->current_ssid == NULL)
 		return 0;
@@ -827,6 +828,11 @@
 	    os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) != 0)
 		return 0;
 
+	sel_ssid = NULL;
+	selected = wpa_supplicant_pick_network(wpa_s, &sel_ssid);
+	if (selected && sel_ssid && sel_ssid->priority > ssid->priority)
+		return 0; /* higher priority network in scan results */
+
 	return 1;
 }