Cumulative patch from commit 00033a0903f69b2f0e0c048840bff059f5a3eab9

00033a0 OpenSSL: Always accept pinned certificates
b2329e4 Add QCA vendor subcmd for Data Offload
1d246a1 Make rate-not-supported debug print more useful
761396e Reject Group Key message 1/2 prior to completion of 4-way handshake
3f0e6ec nl80211: Extend NL80211_CMD_TDLS_OPER to support discovery
c10ca2a TDLS: Allow driver to request TDLS Discovery Request initiation
41312fc mesh: Leave mesh in driver setup if initialization fails
ac8e074 Clear RSN timers for preauth and PTK rekeying on disassociation
f2f65dd Reserve QCA vendor specific nl80211 commands 61..90
088a210 HS 2.0: Add NULL check before dereferencing in hs20-osu-client
bea8d9a nl80211: Use the new bridge port option proxyarp_wifi

Change-Id: I1ef819ab4efa554f059787e02570f48be39819a6
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hs20/client/oma_dm_client.c b/hs20/client/oma_dm_client.c
index 6eaeeb4..5854b72 100644
--- a/hs20/client/oma_dm_client.c
+++ b/hs20/client/oma_dm_client.c
@@ -772,6 +772,11 @@
 	if (node) {
 		char *type;
 		type = xml_node_get_text(ctx->xml, node);
+		if (type == NULL) {
+			wpa_printf(MSG_INFO, "Could not find type text");
+			os_free(locuri);
+			return DM_RESP_BAD_REQUEST;
+		}
 		use_tnds = node &&
 			os_strstr(type, "application/vnd.syncml.dmtnds+xml");
 	}
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index cf04193..2117ee7 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -140,6 +140,8 @@
 	QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED = 58,
 	QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED = 59,
 	QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED = 60,
+	/* 61-90 - reserved for QCA */
+	QCA_NL80211_VENDOR_SUBCMD_DATA_OFFLOAD = 91,
 };
 
 
@@ -220,4 +222,25 @@
 	NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */
 };
 
+/**
+ * enum qca_wlan_vendor_attr_data_offload_ind - Vendor Data Offload Indication
+ *
+ * @QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_SESSION: Session corresponding to
+ *	the offloaded data.
+ * @QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_PROTOCOL: Protocol of the offloaded
+ *	data.
+ * @QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_EVENT: Event type for the data offload
+ *	indication.
+ */
+enum qca_wlan_vendor_attr_data_offload_ind {
+	QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_SESSION,
+	QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_PROTOCOL,
+	QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_EVENT,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_MAX =
+	QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_AFTER_LAST - 1
+};
 #endif /* QCA_VENDOR_H */
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 46c4a46..52db8fc 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -1516,7 +1516,11 @@
 	err_str = X509_verify_cert_error_string(err);
 
 #ifdef CONFIG_SHA256
-	if (preverify_ok && depth == 0 && conn->server_cert_only) {
+	/*
+	 * Do not require preverify_ok so we can explicity allow otherwise
+	 * invalid pinned server certificates.
+	 */
+	if (depth == 0 && conn->server_cert_only) {
 		struct wpabuf *cert;
 		cert = get_x509_cert(err_cert);
 		if (!cert) {
@@ -1534,6 +1538,14 @@
 				err_str = "Server certificate mismatch";
 				err = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
 				preverify_ok = 0;
+			} else if (!preverify_ok) {
+				/*
+				 * Certificate matches pinned certificate, allow
+				 * regardless of other problems.
+				 */
+				wpa_printf(MSG_DEBUG,
+					   "OpenSSL: Ignore validation issues for a pinned server certificate");
+				preverify_ok = 1;
 			}
 			wpabuf_free(cert);
 		}
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index d35309a..03bd1a7 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -4148,7 +4148,8 @@
 		u8 peer[ETH_ALEN];
 		enum {
 			TDLS_REQUEST_SETUP,
-			TDLS_REQUEST_TEARDOWN
+			TDLS_REQUEST_TEARDOWN,
+			TDLS_REQUEST_DISCOVER,
 		} oper;
 		u16 reason_code; /* for teardown */
 	} tdls;
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 2a2ef6f..d743868 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -8305,7 +8305,7 @@
 {
 	switch (attr) {
 	case DRV_BR_PORT_ATTR_PROXYARP:
-		return "proxyarp";
+		return "proxyarp_wifi";
 	case DRV_BR_PORT_ATTR_HAIRPIN_MODE:
 		return "hairpin_mode";
 	}
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index b59d139..87e412d 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -1282,6 +1282,12 @@
 			   MACSTR, MAC2STR(data.tdls.peer));
 		data.tdls.oper = TDLS_REQUEST_TEARDOWN;
 		break;
+	case NL80211_TDLS_DISCOVERY_REQ:
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: TDLS discovery request for peer " MACSTR,
+			   MAC2STR(data.tdls.peer));
+		data.tdls.oper = TDLS_REQUEST_DISCOVER;
+		break;
 	default:
 		wpa_printf(MSG_DEBUG, "nl80211: Unsupported TDLS operatione "
 			   "event");
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index b892a66..8adeef4 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -1244,6 +1244,7 @@
 			sm->cur_pmksa = sa;
 	}
 
+	sm->msg_3_of_4_ok = 1;
 	return;
 
 failed:
@@ -1436,6 +1437,12 @@
 	int rekey, ret;
 	struct wpa_gtk_data gd;
 
+	if (!sm->msg_3_of_4_ok) {
+		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+			"WPA: Group Key Handshake started prior to completion of 4-way handshake");
+		goto failed;
+	}
+
 	os_memset(&gd, 0, sizeof(gd));
 
 	rekey = wpa_sm_get_state(sm) == WPA_COMPLETED;
@@ -2282,6 +2289,8 @@
  */
 void wpa_sm_notify_disassoc(struct wpa_sm *sm)
 {
+	eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL);
+	eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
 	peerkey_deinit(sm);
 	rsn_preauth_deinit(sm);
 	pmksa_cache_clear_current(sm);
@@ -2293,6 +2302,8 @@
 
 	/* Keys are not needed in the WPA state machine anymore */
 	wpa_sm_drop_sa(sm);
+
+	sm->msg_3_of_4_ok = 0;
 }
 
 
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 431bb20..965a9c1 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -23,6 +23,7 @@
 	size_t pmk_len;
 	struct wpa_ptk ptk, tptk;
 	int ptk_set, tptk_set;
+	unsigned int msg_3_of_4_ok:1;
 	u8 snonce[WPA_NONCE_LEN];
 	u8 anonce[WPA_NONCE_LEN]; /* ANonce from the last 1/4 msg */
 	int renew_snonce;
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 94be68f..1f55e0f 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -678,9 +678,10 @@
 				 * order to join a BSS all required rates
 				 * have to be supported by the hardware.
 				 */
-				wpa_dbg(wpa_s, MSG_DEBUG, "   hardware does "
-					"not support required rate %d.%d Mbps",
-					r / 10, r % 10);
+				wpa_dbg(wpa_s, MSG_DEBUG,
+					"   hardware does not support required rate %d.%d Mbps (freq=%d mode==%d num_rates=%d)",
+					r / 10, r % 10,
+					bss->freq, mode->mode, mode->num_rates);
 				return 0;
 			}
 		}
@@ -2498,6 +2499,10 @@
 			wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN,
 					  data->tdls.peer);
 		break;
+	case TDLS_REQUEST_DISCOVER:
+			wpa_tdls_send_discovery_request(wpa_s->wpa,
+							data->tdls.peer);
+		break;
 	}
 }
 #endif /* CONFIG_TDLS */
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index cf3676c..33b4af3 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -344,6 +344,7 @@
 
 	if (wpa_supplicant_mesh_init(wpa_s, ssid)) {
 		wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh");
+		wpa_drv_leave_mesh(wpa_s);
 		ret = -1;
 		goto out;
 	}