Accumulative patch from commit  cc03d0fef3bf5913f8e11b7e998c10bf36a3c07f

  Author: Amar Singhal <asinghal@qca.qualcomm.com>
  Date:   Wed Feb 6 00:31:34 2013 +0200
    Add "BSS LAST ..." command

 - Add "BSS LAST ..." command
 - HS 2.0: Fix IE buffer length for extra scan IEs
 - TDLS: Several fixes
 - P2P: Fix P2P-GROUP-STARTED event for p2p_connect-join
 - P2P: Fix Action frame processing if Interworking is enabled
 - wpa_supplicant: Fix access to the freed memory when removing all networks
 - Add driver for OpenBSD net80211 layer
 - Make wpas_select_network_from_last_scan() static
 - wpa_supplicant: Implement fast-associate on SelectNetwork
 - Update scan interval gracefully
 - eloop: Add a timer cancel that returns the remaining time
 - nl80211: Do not use void pointer for driver_ops used internally
 - hostapd: Fix crash when scan fails

Change-Id: I083747a0b1f7000730a9ab3ea80f3ee7e6247181
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index c38fada..9a79d28 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -680,8 +680,11 @@
 		return -1;
 	pos = rbuf;
 
-	if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success)
+	if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success) {
+		/* Overwrite the reason code */
+		reason_code = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
 		goto skip_ies;
+	}
 
 	ftie = (struct wpa_tdls_ftie *) pos;
 	ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
@@ -715,8 +718,7 @@
 
 	/* request driver to send Teardown using this FTIE */
 	wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_TEARDOWN, 0,
-			  WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED, rbuf,
-			  pos - rbuf);
+			  reason_code, rbuf, pos - rbuf);
 	os_free(rbuf);
 
 	/* clear the Peerkey statemachine */
@@ -868,10 +870,20 @@
 
 
 static struct wpa_tdls_peer *
-wpa_tdls_add_peer(struct wpa_sm *sm, const u8 *addr)
+wpa_tdls_add_peer(struct wpa_sm *sm, const u8 *addr, int *existing)
 {
 	struct wpa_tdls_peer *peer;
 
+	if (existing)
+		*existing = 0;
+	for (peer = sm->tdls; peer; peer = peer->next) {
+		if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) {
+			if (existing)
+				*existing = 1;
+			return peer; /* re-use existing entry */
+		}
+	}
+
 	wpa_printf(MSG_INFO, "TDLS: Creating peer entry for " MACSTR,
 		   MAC2STR(addr));
 
@@ -1282,7 +1294,7 @@
 		return -1;
 	}
 
-	peer = wpa_tdls_add_peer(sm, addr);
+	peer = wpa_tdls_add_peer(sm, addr, NULL);
 	if (peer == NULL)
 		return -1;
 
@@ -1352,18 +1364,9 @@
 
 	wpa_printf(MSG_INFO, "TDLS: Dialog Token in TPK M1 %d", dtoken);
 
-	for (peer = sm->tdls; peer; peer = peer->next) {
-		if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0) {
-			existing_peer = 1;
-			break;
-		}
-	}
-
-	if (peer == NULL) {
-		peer = wpa_tdls_add_peer(sm, src_addr);
-		if (peer == NULL)
-			goto error;
-	}
+	peer = wpa_tdls_add_peer(sm, src_addr, &existing_peer);
+	if (peer == NULL)
+		goto error;
 
 	/* capability information */
 	peer->capability = WPA_GET_LE16(cpos);
@@ -1397,15 +1400,9 @@
 
 #ifdef CONFIG_TDLS_TESTING
 	if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
-		for (peer = sm->tdls; peer; peer = peer->next) {
-			if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
-				break;
-		}
-		if (peer == NULL) {
-			peer = wpa_tdls_add_peer(sm, src_addr);
-			if (peer == NULL)
-				goto error;
-		}
+		peer = wpa_tdls_add_peer(sm, src_addr, NULL);
+		if (peer == NULL)
+			goto error;
 		wpa_printf(MSG_DEBUG, "TDLS: Testing concurrent initiation of "
 			   "TDLS setup - send own request");
 		peer->initiator = 1;
@@ -2058,18 +2055,9 @@
 		return -1;
 	}
 
-	/* Find existing entry and if found, use that instead of adding
-	 * a new one */
-	for (peer = sm->tdls; peer; peer = peer->next) {
-		if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
-			break;
-	}
-
-	if (peer == NULL) {
-		peer = wpa_tdls_add_peer(sm, addr);
-		if (peer == NULL)
-			return -1;
-	}
+	peer = wpa_tdls_add_peer(sm, addr, NULL);
+	if (peer == NULL)
+		return -1;
 
 	peer->initiator = 1;
 
@@ -2085,12 +2073,12 @@
 }
 
 
-int wpa_tdls_reneg(struct wpa_sm *sm, const u8 *addr)
+void wpa_tdls_remove(struct wpa_sm *sm, const u8 *addr)
 {
 	struct wpa_tdls_peer *peer;
 
 	if (sm->tdls_disabled || !sm->tdls_supported)
-		return -1;
+		return;
 
 	for (peer = sm->tdls; peer; peer = peer->next) {
 		if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
@@ -2098,7 +2086,7 @@
 	}
 
 	if (peer == NULL || !peer->tpk_success)
-		return -1;
+		return;
 
 	if (sm->tdls_external_setup) {
 		/*
@@ -2107,8 +2095,6 @@
 		 */
 		wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
 	}
-
-	return wpa_tdls_start(sm, addr);
 }