diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c index 4d16428f7..f07ef874e 100644 --- a/src/drivers/driver_nl80211_scan.c +++ b/src/drivers/driver_nl80211_scan.c @@ -651,7 +651,6 @@ int bss_info_handler(struct nl_msg *msg, void *arg) const u8 *ie, *beacon_ie; size_t ie_len, beacon_ie_len; u8 *pos; - size_t i; nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); @@ -759,46 +758,6 @@ int bss_info_handler(struct nl_msg *msg, void *arg) } } - /* - * cfg80211 maintains separate BSS table entries for APs if the same - * BSSID,SSID pair is seen on multiple channels. wpa_supplicant does - * not use frequency as a separate key in the BSS table, so filter out - * duplicated entries. Prefer associated BSS entry in such a case in - * order to get the correct frequency into the BSS table. Similarly, - * prefer newer entries over older. - */ - for (i = 0; i < res->num; i++) { - const u8 *s1, *s2; - if (os_memcmp(res->res[i]->bssid, r->bssid, ETH_ALEN) != 0) - continue; - - s1 = get_ie((u8 *) (res->res[i] + 1), - res->res[i]->ie_len, WLAN_EID_SSID); - s2 = get_ie((u8 *) (r + 1), r->ie_len, WLAN_EID_SSID); - if (s1 == NULL || s2 == NULL || s1[1] != s2[1] || - os_memcmp(s1, s2, 2 + s1[1]) != 0) - continue; - - /* Same BSSID,SSID was already included in scan results */ - wpa_printf(MSG_DEBUG, - "nl80211: Remove duplicated scan result for " MACSTR - " (assoc/age/freq prev=%d/%d/%d new=%d/%d/%d)", - MAC2STR(r->bssid), - !!(res->res[i]->flags & WPA_SCAN_ASSOCIATED), - res->res[i]->age, res->res[i]->freq, - !!(r->flags & WPA_SCAN_ASSOCIATED), - r->age, r->freq); - - if (((r->flags & WPA_SCAN_ASSOCIATED) && - !(res->res[i]->flags & WPA_SCAN_ASSOCIATED)) || - r->age < res->res[i]->age) { - os_free(res->res[i]); - res->res[i] = r; - } else - os_free(r); - return NL_SKIP; - } - tmp = os_realloc_array(res->res, res->num + 1, sizeof(struct wpa_scan_res *)); if (tmp == NULL) { diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 3a8778db9..44a9a7b2c 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -595,6 +595,42 @@ wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, { u32 changes; + if (bss->last_update_idx == wpa_s->bss_update_idx) { + struct os_reltime update_time; + + /* + * Some drivers (e.g., cfg80211) include multiple BSS entries + * for the same BSS if that BSS's channel changes. The BSS list + * implementation in wpa_supplicant does not do that and we need + * to filter out the obsolete results here to make sure only the + * most current BSS information remains in the table. + */ + wpa_printf(MSG_DEBUG, "BSS: " MACSTR + " has multiple entries in the scan results - select the most current one", + MAC2STR(bss->bssid)); + calculate_update_time(fetch_time, res->age, &update_time); + wpa_printf(MSG_DEBUG, + "Previous last_update: %u.%06u (freq %d%s)", + (unsigned int) bss->last_update.sec, + (unsigned int) bss->last_update.usec, + bss->freq, + (bss->flags & WPA_BSS_ASSOCIATED) ? " assoc" : ""); + wpa_printf(MSG_DEBUG, "New last_update: %u.%06u (freq %d%s)", + (unsigned int) update_time.sec, + (unsigned int) update_time.usec, + res->freq, + (res->flags & WPA_SCAN_ASSOCIATED) ? " assoc" : ""); + if ((bss->flags & WPA_BSS_ASSOCIATED) || + (!(res->flags & WPA_SCAN_ASSOCIATED) && + !os_reltime_before(&bss->last_update, &update_time))) { + wpa_printf(MSG_DEBUG, + "Ignore this BSS entry since the previous update looks more current"); + return bss; + } + wpa_printf(MSG_DEBUG, + "Accept this BSS entry since it looks more current than the previous update"); + } + changes = wpa_bss_compare_res(bss, res); if (changes & WPA_BSS_FREQ_CHANGED_FLAG) wpa_printf(MSG_DEBUG, "BSS: " MACSTR " changed freq %d --> %d",