Cumulative patch from commit 39a5800f7c2a9de743c673a78929ac46a099b1a4

39a5800 wpa_supplicant: Allow disabling LDPC
7230040 Interworking: Read IMSI if not read at supplicant start
62f736d Interworking: Init scard when a credential requires SIM access
729897a Interworking: Fix incorrect compile PCSC flag
21611ea edit: Increase buffer size to 4096 bytes
0b2c59e OSU server: Add example scripts for Hotspot 2.0 PKI
0f27c20 HS 2.0R2: Add example OSU SPP server implementation
1e03c6c XML: Remove forgotten, unused definition of debug_print_func
5cfc87b Make hs20_wan_metrics parser error print more helpful
4be20bf Fix validation of anqp_3gpp_cell_net configuration parameter
23587e3 Remove duplicated vht_capab parser entry
18a8e55 Notify STA of disconnection based on ACL change
8943cc9 RADIUS server: Add support for MAC ACL
dc87541 Clean up debug print for PSK file search
bbbacbf DFS: Print CAC info in ctrl_iface STATUS command
ace0fbd P2P: Fix segfault when PBC overlap is detected
cf15b15 Add writing of network block ocsp parameter
5c9da16 nl80211: Set all BSS interfaces down when tearing down AP in MBSS mode
f1c4dbf wpa_supplicant: Remove pending sme-connect radio work
4f560cd wpa_supplicant: Override HT A-MPDU size if VHT A-MPDU was overridden
3ae8b7b hostapd: Add vendor command support
782e2f7 P2P: Do not initiate scan on P2P Device when enabled
74a1319 Fix issue with incorrect secondary_channel in HT40/HT80
96ecea5 Pass TDLS peer capability information in tdls_mgmt
78cd7e6 Sync with wireless-testing.git include/uapi/linux/nl80211.h
b36935b nl80211: Fix EAPOL frames not being delivered
6997f8b nl80211: Set interface address even if using old interface
9b4d9c8 nl80211: Print if_indices list in debug log
762c41a eloop: Add assert() on negative fd when using select() code path
978c673 Add a note on using 'iw list' to determine multi-BSS support

Change-Id: I89af7f8d92ed706c8909ed3cc9c49d6e1277a2b0
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index 9b8ca6b..62a2a59 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -118,6 +118,7 @@
 		u8 action_code; /* TDLS frame type */
 		u8 dialog_token;
 		u16 status_code;
+		u32 peer_capab;
 		int buf_len;    /* length of TPK message for retransmission */
 		u8 *buf;        /* buffer for TPK message */
 	} sm_tmr;
@@ -142,6 +143,8 @@
 
 	u8 *supp_oper_classes;
 	size_t supp_oper_classes_len;
+
+	u8 wmm_capable;
 };
 
 
@@ -211,15 +214,16 @@
 
 static int wpa_tdls_send_tpk_msg(struct wpa_sm *sm, const u8 *dst,
 				 u8 action_code, u8 dialog_token,
-				 u16 status_code, const u8 *buf, size_t len)
+				 u16 status_code, u32 peer_capab,
+				 const u8 *buf, size_t len)
 {
 	return wpa_sm_send_tdls_mgmt(sm, dst, action_code, dialog_token,
-				     status_code, buf, len);
+				     status_code, peer_capab, buf, len);
 }
 
 
 static int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code,
-			     u8 dialog_token, u16 status_code,
+			     u8 dialog_token, u16 status_code, u32 peer_capab,
 			     const u8 *msg, size_t msg_len)
 {
 	struct wpa_tdls_peer *peer;
@@ -230,7 +234,7 @@
 		   (unsigned int) msg_len);
 
 	if (wpa_tdls_send_tpk_msg(sm, dest, action_code, dialog_token,
-				  status_code, msg, msg_len)) {
+				  status_code, peer_capab, msg, msg_len)) {
 		wpa_printf(MSG_INFO, "TDLS: Failed to send message "
 			   "(action_code=%u)", action_code);
 		return -1;
@@ -268,6 +272,7 @@
 	peer->sm_tmr.action_code = action_code;
 	peer->sm_tmr.dialog_token = dialog_token;
 	peer->sm_tmr.status_code = status_code;
+	peer->sm_tmr.peer_capab = peer_capab;
 	peer->sm_tmr.buf_len = msg_len;
 	os_free(peer->sm_tmr.buf);
 	peer->sm_tmr.buf = os_malloc(msg_len);
@@ -324,6 +329,7 @@
 					  peer->sm_tmr.action_code,
 					  peer->sm_tmr.dialog_token,
 					  peer->sm_tmr.status_code,
+					  peer->sm_tmr.peer_capab,
 					  peer->sm_tmr.buf,
 					  peer->sm_tmr.buf_len)) {
 			wpa_printf(MSG_INFO, "TDLS: Failed to retry "
@@ -645,6 +651,8 @@
 	peer->supp_oper_classes = NULL;
 	peer->rsnie_i_len = peer->rsnie_p_len = 0;
 	peer->cipher = 0;
+	peer->qos_info = 0;
+	peer->wmm_capable = 0;
 	peer->tpk_set = peer->tpk_success = 0;
 	os_memset(&peer->tpk, 0, sizeof(peer->tpk));
 	os_memset(peer->inonce, 0, WPA_NONCE_LEN);
@@ -747,7 +755,7 @@
 
 	/* request driver to send Teardown using this FTIE */
 	wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_TEARDOWN, 0,
-			  reason_code, rbuf, pos - rbuf);
+			  reason_code, 0, rbuf, pos - rbuf);
 	os_free(rbuf);
 
 	/* clear the Peerkey statemachine */
@@ -918,7 +926,7 @@
 		   " (action=%u status=%u)",
 		   MAC2STR(dst), tdls_action, status);
 	return wpa_tdls_tpk_send(sm, dst, tdls_action, dialog_token, status,
-				 NULL, 0);
+				 0, NULL, 0);
 }
 
 
@@ -1124,7 +1132,7 @@
 		   MAC2STR(peer->addr));
 
 	status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_SETUP_REQUEST,
-				   1, 0, rbuf, pos - rbuf);
+				   1, 0, 0, rbuf, pos - rbuf);
 	os_free(rbuf);
 
 	return status;
@@ -1208,7 +1216,7 @@
 
 skip_ies:
 	status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE,
-				   dtoken, 0, rbuf, pos - rbuf);
+				   dtoken, 0, 0, rbuf, pos - rbuf);
 	os_free(rbuf);
 
 	return status;
@@ -1226,6 +1234,7 @@
 	struct wpa_tdls_timeoutie timeoutie;
 	u32 lifetime;
 	int status;
+	u32 peer_capab = 0;
 
 	buf_len = 0;
 	if (wpa_tdls_get_privacy(sm)) {
@@ -1288,9 +1297,16 @@
 	wpa_tdls_ftie_mic(peer->tpk.kck, 3, (u8 *) lnkid, peer->rsnie_p,
 			  (u8 *) &timeoutie, (u8 *) ftie, ftie->mic);
 
+	if (peer->vht_capabilities)
+		peer_capab |= TDLS_PEER_VHT;
+	else if (peer->ht_capabilities)
+		peer_capab |= TDLS_PEER_HT;
+	else if (peer->wmm_capable)
+		peer_capab |= TDLS_PEER_WMM;
+
 skip_ies:
 	status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM,
-				   dtoken, 0, rbuf, pos - rbuf);
+				   dtoken, 0, peer_capab, rbuf, pos - rbuf);
 	os_free(rbuf);
 
 	return status;
@@ -1305,7 +1321,7 @@
 		   "(peer " MACSTR ")", MAC2STR(peer->addr));
 
 	return wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE,
-				 dialog_token, 0, NULL, 0);
+				 dialog_token, 0, 0, NULL, 0);
 }
 
 
@@ -1366,7 +1382,7 @@
 	wpa_printf(MSG_DEBUG, "TDLS: Sending Discovery Request to peer "
 		   MACSTR, MAC2STR(addr));
 	return wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_DISCOVERY_REQUEST,
-				 1, 0, NULL, 0);
+				 1, 0, 0, NULL, 0);
 }
 
 
@@ -1484,6 +1500,8 @@
 	wmm = (struct wmm_information_element *) kde->wmm;
 	peer->qos_info = wmm->qos_info;
 
+	peer->wmm_capable = 1;
+
 	wpa_printf(MSG_DEBUG, "TDLS: Peer WMM QOS Info 0x%x", peer->qos_info);
 	return 0;
 }
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index 20b3f62..df10342 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -54,7 +54,8 @@
 			     int *tdls_ext_setup);
 	int (*send_tdls_mgmt)(void *ctx, const u8 *dst,
 			      u8 action_code, u8 dialog_token,
-			      u16 status_code, const u8 *buf, size_t len);
+			      u16 status_code, u32 peer_capab,
+			      const u8 *buf, size_t len);
 	int (*tdls_oper)(void *ctx, int oper, const u8 *peer);
 	int (*tdls_peer_addset)(void *ctx, const u8 *addr, int add, u16 aid,
 				u16 capability, const u8 *supp_rates,
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 75cfb47..f2fd285 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -267,13 +267,13 @@
 
 static inline int wpa_sm_send_tdls_mgmt(struct wpa_sm *sm, const u8 *dst,
 					u8 action_code, u8 dialog_token,
-					u16 status_code, const u8 *buf,
-					size_t len)
+					u16 status_code, u32 peer_capab,
+					const u8 *buf, size_t len)
 {
 	if (sm->ctx->send_tdls_mgmt)
 		return sm->ctx->send_tdls_mgmt(sm->ctx->ctx, dst, action_code,
 					       dialog_token, status_code,
-					       buf, len);
+					       peer_capab, buf, len);
 	return -1;
 }