Browse Source

WPS: Use latest updated BSS entry if multiple BSSID matches found

If the AP (P2P GO) has changes its channel of SSID recently, the BSS
table may have multiple entries for a BSSID. Select the one which was
most recently updated for WPS/P2P operations in such case to increase
the likelihood of using current information.

Signed-hostap: Jouni Malinen <j@w1.fi>
Jouni Malinen 12 years ago
parent
commit
702621e6dd
4 changed files with 35 additions and 5 deletions
  1. 28 0
      wpa_supplicant/bss.c
  2. 2 0
      wpa_supplicant/bss.h
  3. 4 4
      wpa_supplicant/p2p_supplicant.c
  4. 1 1
      wpa_supplicant/wps_supplicant.c

+ 28 - 0
wpa_supplicant/bss.c

@@ -829,6 +829,34 @@ struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s,
 }
 
 
+/**
+ * wpa_bss_get_bssid_latest - Fetch the latest BSS table entry based on BSSID
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @bssid: BSSID
+ * Returns: Pointer to the BSS entry or %NULL if not found
+ *
+ * This function is like wpa_bss_get_bssid(), but full BSS table is iterated to
+ * find the entry that has the most recent update. This can help in finding the
+ * correct entry in cases where the SSID of the AP may have changed recently
+ * (e.g., in WPS reconfiguration cases).
+ */
+struct wpa_bss * wpa_bss_get_bssid_latest(struct wpa_supplicant *wpa_s,
+					  const u8 *bssid)
+{
+	struct wpa_bss *bss, *found = NULL;
+	if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
+		return NULL;
+	dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
+		if (os_memcmp(bss->bssid, bssid, ETH_ALEN) != 0)
+			continue;
+		if (found == NULL ||
+		    os_time_before(&found->last_update, &bss->last_update))
+			found = bss;
+	}
+	return found;
+}
+
+
 #ifdef CONFIG_P2P
 /**
  * wpa_bss_get_p2p_dev_addr - Fetch a BSS table entry based on P2P Device Addr

+ 2 - 0
wpa_supplicant/bss.h

@@ -109,6 +109,8 @@ struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
 			     const u8 *ssid, size_t ssid_len);
 struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s,
 				   const u8 *bssid);
+struct wpa_bss * wpa_bss_get_bssid_latest(struct wpa_supplicant *wpa_s,
+					  const u8 *bssid);
 struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s,
 					  const u8 *dev_addr);
 struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id);

+ 4 - 4
wpa_supplicant/p2p_supplicant.c

@@ -3344,8 +3344,8 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
 		if (join == 0 &&
 		    wpa_s->auto_pd_scan_retry < P2P_AUTO_PD_SCAN_ATTEMPTS) {
 			wpa_s->auto_pd_scan_retry++;
-			bss = wpa_bss_get_bssid(wpa_s,
-						wpa_s->pending_join_dev_addr);
+			bss = wpa_bss_get_bssid_latest(
+				wpa_s, wpa_s->pending_join_dev_addr);
 			if (bss) {
 				freq = bss->freq;
 				wpa_printf(MSG_DEBUG, "P2P: Scan retry %d for "
@@ -3425,7 +3425,7 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
 		wpa_printf(MSG_DEBUG, "P2P: Target GO operating frequency "
 			   "from P2P peer table: %d MHz", freq);
 	}
-	bss = wpa_bss_get_bssid(wpa_s, wpa_s->pending_join_iface_addr);
+	bss = wpa_bss_get_bssid_latest(wpa_s, wpa_s->pending_join_iface_addr);
 	if (bss) {
 		freq = bss->freq;
 		wpa_printf(MSG_DEBUG, "P2P: Target GO operating frequency "
@@ -3627,7 +3627,7 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s)
 	os_memcpy(res.peer_interface_addr, wpa_s->pending_join_iface_addr,
 		  ETH_ALEN);
 	res.wps_method = wpa_s->pending_join_wps_method;
-	bss = wpa_bss_get_bssid(wpa_s, wpa_s->pending_join_iface_addr);
+	bss = wpa_bss_get_bssid_latest(wpa_s, wpa_s->pending_join_iface_addr);
 	if (bss) {
 		res.freq = bss->freq;
 		res.ssid_len = bss->ssid_len;

+ 1 - 1
wpa_supplicant/wps_supplicant.c

@@ -873,7 +873,7 @@ static void wpas_wps_reassoc(struct wpa_supplicant *wpa_s,
 
 	wpa_s->known_wps_freq = 0;
 	if (bssid) {
-		bss = wpa_bss_get_bssid(wpa_s, bssid);
+		bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
 		if (bss && bss->freq > 0) {
 			wpa_s->known_wps_freq = 1;
 			wpa_s->wps_freq = bss->freq;