Accumulative patch from commit b618a469c42120e984ab1c85ed6058504d1fca78

  Author: Jouni Malinen <jouni@qca.qualcomm.com>
  Date:   Sat Feb 16 19:54:09 2013 +0200
    Interworking: Select highest priority cred if multiple matches

Interworking: Select highest priority cred if multiple matches
GAS server: Fix a regression in GAS server callback
hostapd: Fix Max SP Length derivation from QoS Info
nl80211: Configure STA Capabilities and Extended Capabilities
Synchronize with wireless-testing.git include/uapi/linux/nl80211.h
WPS: Fix build without CONFIG_WPS_NFC
WPS: Add support for NFC handover select generation with wpa_supplicant
WPS: Update NFC connection handover documentation
WPS: Add support for config token generation with wpa_supplicant
WPS: Allow password token to be written with nfcpy
WPS: Use pre-configured NFC password token instead of overriding it
TDLS: Pass peer's Capability and Ext Capability info during sta_add
TDLS: Pass peer's HT Capability and QOS information during sta_add
nl80211: Add debug prints for STA add/set operations
TDLS: Fix add/set STA operation
Synchronize with wireless-testing.git include/uapi/linux/nl80211.h
WPS: Allow Device Password to be changed from M1 to M2
WPS: Fix wps_reg nfc-pw option
TDLS: Tear down peers when disconnecting from the AP
P2P: Do not use old scan result data for peer discovery
Use more accurate timestamps for scan results
P2P: Postpone P2P-DEVICE-FOUND if config_methods not known
P2P: Do not allow peer update to clear config_methods
WPS: Report NFC connection handover completion differently
P2P: Avoid concurrent scans during all steps of group formation
P2P: Cancel group formation timeout on group removal (on client)
WPS: Change listen time to match nfcpy default (250 ms)
WPS: Report only the carrier record from NFC to wpa_supplicant
WPS: Fetch only the carrier record from wpa_supplicant for NFC
WPS: Update nfcpy script to support AP mode NFC connection handover
WPS: Add command for fetching carrier record for NFC handover
WPS: Clean up debug prints with nfcpy
WPS: Remove 0.5 sec extra wait from NFC handover with nfcpy
WPS: Use alternating poll/listen for NFC peer discovery with nfcpy
WPS: Configure logging to show nfcpy log message
WPS: Add an example python script for NFC operations with hostapd
hostapd: Do not change HT40 capability due to OBSS scan
dbus: Add missing signal description for WPS (7)
EAP peer: Add Session-Id derivation to more EAP methods
EAP peer: Add Session-Id derivation
EAP-IKEV2 server: Fix invalid memory freeing operation
eap_proxy: Add a dummy implementation for compilation testing
eap_proxy: Add mechanism for allowing EAP methods to be offloaded
Android: Allow setgroups to be overridden from build configuration
P2P: Send p2p_stop_find event on failure to start pending p2p_find
P2P: Fix GO Probe Response IEs when Wi-Fi Display is enabled
Capability matching for 60 GHz band
nl80211: Add ctrl_iface message for AP mode connection rejection
P2P: Allow local configuration to use 5 GHz band 40 MHz channels
Fix BSS RANGE command for no exact id match cases

Change-Id: Iac9284bba31db40911aecc3adf2843c9b1576db1
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index aaacc9a..985227c 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -617,8 +617,18 @@
 	}
 
 	if (!probe_req) {
-		dev->info.config_methods = msg->config_methods ?
+		u16 new_config_methods;
+		new_config_methods = msg->config_methods ?
 			msg->config_methods : msg->wps_config_methods;
+		if (new_config_methods &&
+		    dev->info.config_methods != new_config_methods) {
+			wpa_printf(MSG_DEBUG, "P2P: Update peer " MACSTR
+				   " config_methods 0x%x -> 0x%x",
+				   MAC2STR(dev->info.p2p_device_addr),
+				   dev->info.config_methods,
+				   new_config_methods);
+			dev->info.config_methods = new_config_methods;
+		}
 	}
 }
 
@@ -630,7 +640,7 @@
  *	P2P Device Address or P2P Interface Address)
  * @level: Signal level (signal strength of the received frame from the peer)
  * @freq: Frequency on which the Beacon or Probe Response frame was received
- * @age_ms: Age of the information in milliseconds
+ * @rx_time: Time when the result was received
  * @ies: IEs from the Beacon or Probe Response frame
  * @ies_len: Length of ies buffer in octets
  * @scan_res: Whether this was based on scan results
@@ -642,14 +652,14 @@
  * Info attributes.
  */
 int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq,
-		   unsigned int age_ms, int level, const u8 *ies,
+		   struct os_time *rx_time, int level, const u8 *ies,
 		   size_t ies_len, int scan_res)
 {
 	struct p2p_device *dev;
 	struct p2p_message msg;
 	const u8 *p2p_dev_addr;
 	int i;
-	struct os_time time_now, time_tmp_age, entry_ts;
+	struct os_time time_now;
 
 	os_memset(&msg, 0, sizeof(msg));
 	if (p2p_parse_ies(ies, ies_len, &msg)) {
@@ -686,22 +696,29 @@
 		return -1;
 	}
 
-	os_get_time(&time_now);
-	time_tmp_age.sec = age_ms / 1000;
-	time_tmp_age.usec = (age_ms % 1000) * 1000;
-	os_time_sub(&time_now, &time_tmp_age, &entry_ts);
+	if (rx_time == NULL) {
+		os_get_time(&time_now);
+		rx_time = &time_now;
+	}
 
 	/*
 	 * Update the device entry only if the new peer
 	 * entry is newer than the one previously stored.
 	 */
-	if (dev->last_seen.usec > 0 &&
-	    os_time_before(&entry_ts, &dev->last_seen)) {
+	if (dev->last_seen.sec > 0 &&
+	    os_time_before(rx_time, &dev->last_seen)) {
+		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Do not update peer "
+			"entry based on old frame (rx_time=%u.%06u "
+			"last_seen=%u.%06u)",
+			(unsigned int) rx_time->sec,
+			(unsigned int) rx_time->usec,
+			(unsigned int) dev->last_seen.sec,
+			(unsigned int) dev->last_seen.usec);
 		p2p_parse_free(&msg);
 		return -1;
 	}
 
-	os_memcpy(&dev->last_seen, &entry_ts, sizeof(struct os_time));
+	os_memcpy(&dev->last_seen, rx_time, sizeof(struct os_time));
 
 	dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY);
 
@@ -780,13 +797,37 @@
 		return 0;
 
 	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-		"P2P: Peer found with Listen frequency %d MHz", freq);
+		"P2P: Peer found with Listen frequency %d MHz "
+		"(rx_time=%u.%06u)", freq, (unsigned int) rx_time->sec,
+		(unsigned int) rx_time->usec);
 	if (dev->flags & P2P_DEV_USER_REJECTED) {
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			"P2P: Do not report rejected device");
 		return 0;
 	}
 
+	if (dev->info.config_methods == 0 &&
+	    (freq == 2412 || freq == 2437 || freq == 2462)) {
+		/*
+		 * If we have only seen a Beacon frame from a GO, we do not yet
+		 * know what WPS config methods it supports. Since some
+		 * applications use config_methods value from P2P-DEVICE-FOUND
+		 * events, postpone reporting this peer until we've fully
+		 * discovered its capabilities.
+		 *
+		 * At least for now, do this only if the peer was detected on
+		 * one of the social channels since that peer can be easily be
+		 * found again and there are no limitations of having to use
+		 * passive scan on this channels, so this can be done through
+		 * Probe Response frame that includes the config_methods
+		 * information.
+		 */
+		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+			"P2P: Do not report peer " MACSTR " with unknown "
+			"config methods", MAC2STR(addr));
+		return 0;
+	}
+
 	p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info,
 			    !(dev->flags & P2P_DEV_REPORTED_ONCE));
 	dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
@@ -1031,6 +1072,7 @@
 
 	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting find (type=%d)",
 		type);
+	os_get_time(&p2p->find_start);
 	if (p2p->p2p_scan_running) {
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan is "
 			"already running");
@@ -1133,8 +1175,10 @@
 		"now that previous scan was completed");
 	if (p2p_find(p2p, p2p->last_p2p_find_timeout, p2p->find_type,
 		     p2p->num_req_dev_types, p2p->req_dev_types,
-		     p2p->find_dev_id, p2p->search_delay) < 0)
+		     p2p->find_dev_id, p2p->search_delay) < 0) {
+		wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, P2P_EVENT_FIND_STOPPED);
 		return 0;
+	}
 	return 1;
 }
 
@@ -2887,10 +2931,25 @@
 
 
 int p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq,
-			 unsigned int age, int level, const u8 *ies,
+			 struct os_time *rx_time, int level, const u8 *ies,
 			 size_t ies_len)
 {
-	p2p_add_device(p2p, bssid, freq, age, level, ies, ies_len, 1);
+	if (os_time_before(rx_time, &p2p->find_start)) {
+		/*
+		 * The driver may have cached (e.g., in cfg80211 BSS table) the
+		 * scan results for relatively long time. To avoid reporting
+		 * stale information, update P2P peers only based on results
+		 * that have based on frames received after the last p2p_find
+		 * operation was started.
+		 */
+		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Ignore old scan "
+			"result for " MACSTR " (rx_time=%u.%06u)",
+			MAC2STR(bssid), (unsigned int) rx_time->sec,
+			(unsigned int) rx_time->usec);
+		return 0;
+	}
+
+	p2p_add_device(p2p, bssid, freq, rx_time, level, ies, ies_len, 1);
 
 	return 0;
 }
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 18e733b..0663fbb 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -1200,7 +1200,7 @@
  * @p2p: P2P module context from p2p_init()
  * @bssid: BSSID of the scan result
  * @freq: Frequency of the channel on which the device was found in MHz
- * @age: Age of the scan result in milliseconds
+ * @rx_time: Time when the result was received
  * @level: Signal level (signal strength of the received Beacon/Probe Response
  *	frame)
  * @ies: Pointer to IEs from the scan result
@@ -1222,7 +1222,7 @@
  * start of a pending operation, e.g., to start a pending GO negotiation.
  */
 int p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq,
-			 unsigned int age, int level, const u8 *ies,
+			 struct os_time *rx_time, int level, const u8 *ies,
 			 size_t ies_len);
 
 /**
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index 712544b..b2a3d3f 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -403,6 +403,8 @@
 	u8 *find_dev_id;
 	u8 find_dev_id_buf[ETH_ALEN];
 
+	struct os_time find_start; /* time of last p2p_find start */
+
 	struct p2p_group **groups;
 	size_t num_groups;
 
@@ -706,7 +708,7 @@
 void p2p_add_dev_info(struct p2p_data *p2p, const u8 *addr,
 		      struct p2p_device *dev, struct p2p_message *msg);
 int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq,
-		   unsigned int age_ms, int level, const u8 *ies,
+		   struct os_time *rx_time, int level, const u8 *ies,
 		   size_t ies_len, int scan_res);
 struct p2p_device * p2p_get_device(struct p2p_data *p2p, const u8 *addr);
 struct p2p_device * p2p_get_device_interface(struct p2p_data *p2p,
diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c
index ac67932..9283113 100644
--- a/src/p2p/p2p_invitation.c
+++ b/src/p2p/p2p_invitation.c
@@ -176,7 +176,7 @@
 			"P2P: Invitation Request from unknown peer "
 			MACSTR, MAC2STR(sa));
 
-		if (p2p_add_device(p2p, sa, rx_freq, 0, 0, data + 1, len - 1,
+		if (p2p_add_device(p2p, sa, rx_freq, NULL, 0, data + 1, len - 1,
 				   0)) {
 			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 				"P2P: Invitation Request add device failed "
diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c
index ca33f17..44db682 100644
--- a/src/p2p/p2p_pd.c
+++ b/src/p2p/p2p_pd.c
@@ -152,7 +152,7 @@
 			"P2P: Provision Discovery Request from "
 			"unknown peer " MACSTR, MAC2STR(sa));
 
-		if (p2p_add_device(p2p, sa, rx_freq, 0, 0, data + 1, len - 1,
+		if (p2p_add_device(p2p, sa, rx_freq, NULL, 0, data + 1, len - 1,
 				   0)) {
 			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			        "P2P: Provision Discovery Request add device "