static struct wpa_bss * wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, struct wpa_scan_results *scan_res, struct wpa_ssid *group, struct wpa_ssid **selected_ssid) { size_t i; wpa_printf(MSG_DEBUG, "Selecting BSS from priority group %d", group->priority); for (i = 0; i < scan_res->num; i++) { struct wpa_scan_res *bss = scan_res->res[i]; const u8 *ie, *ssid; u8 ssid_len; *selected_ssid = wpa_scan_res_match(wpa_s, i, bss, group); if (!*selected_ssid) continue; ie = wpa_scan_get_ie(bss, WLAN_EID_SSID); ssid = ie ? ie + 2 : (u8 *) ""; ssid_len = ie ? ie[1] : 0; wpa_printf(MSG_DEBUG, " selected BSS " MACSTR " ssid='%s'", MAC2STR(bss->bssid), wpa_ssid_txt(ssid, ssid_len)); return wpa_bss_get(wpa_s, bss->bssid, ssid, ssid_len); } return NULL; }
static int wnm_add_cand_list(struct wpa_supplicant *wpa_s, u8 *buf, size_t len) { u8 *pos = buf; unsigned int i, pref = 255; struct os_reltime now; struct wpa_ssid *ssid = wpa_s->current_ssid; if (!ssid) return 0; /* * TODO: Define when scan results are no longer valid for the candidate * list. */ os_get_reltime(&now); if (os_reltime_expired(&now, &wpa_s->last_scan, 10)) return 0; wpa_printf(MSG_DEBUG, "WNM: Add candidate list to BSS Transition Management Response frame"); for (i = 0; i < wpa_s->last_scan_res_used && pref; i++) { struct wpa_bss *bss = wpa_s->last_scan_res[i]; int res; if (wpa_scan_res_match(wpa_s, i, bss, ssid, 1, 0)) { res = wnm_nei_rep_add_bss(wpa_s, bss, pos, len, pref--); if (res == -2) continue; /* could not build entry for BSS */ if (res < 0) break; /* no more room for candidates */ if (pref == 1) break; pos += res; len -= res; } } wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Management Response candidate list", buf, pos - buf); return pos - buf; }
static struct wpa_bss * compare_scan_neighbor_results(struct wpa_supplicant *wpa_s, os_time_t age_secs, enum mbo_transition_reject_reason *reason) { u8 i; struct wpa_bss *bss = wpa_s->current_bss; struct wpa_bss *target; if (!bss) return NULL; wpa_printf(MSG_DEBUG, "WNM: Current BSS " MACSTR " RSSI %d", MAC2STR(wpa_s->bssid), bss->level); wnm_clear_acceptable(wpa_s); for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) { struct neighbor_report *nei; nei = &wpa_s->wnm_neighbor_report_elements[i]; if (nei->preference_present && nei->preference == 0) { wpa_printf(MSG_DEBUG, "Skip excluded BSS " MACSTR, MAC2STR(nei->bssid)); continue; } target = wpa_bss_get_bssid(wpa_s, nei->bssid); if (!target) { wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR " (pref %d) not found in scan results", MAC2STR(nei->bssid), nei->preference_present ? nei->preference : -1); continue; } if (age_secs) { struct os_reltime now; if (os_get_reltime(&now) == 0 && os_reltime_expired(&now, &target->last_update, age_secs)) { wpa_printf(MSG_DEBUG, "Candidate BSS is more than %ld seconds old", age_secs); continue; } } if (bss->ssid_len != target->ssid_len || os_memcmp(bss->ssid, target->ssid, bss->ssid_len) != 0) { /* * TODO: Could consider allowing transition to another * ESS if PMF was enabled for the association. */ wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR " (pref %d) in different ESS", MAC2STR(nei->bssid), nei->preference_present ? nei->preference : -1); continue; } if (wpa_s->current_ssid && !wpa_scan_res_match(wpa_s, 0, target, wpa_s->current_ssid, 1, 0)) { wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR " (pref %d) does not match the current network profile", MAC2STR(nei->bssid), nei->preference_present ? nei->preference : -1); continue; } if (wpa_is_bss_tmp_disallowed(wpa_s, target->bssid)) { wpa_printf(MSG_DEBUG, "MBO: Candidate BSS " MACSTR " retry delay is not over yet", MAC2STR(nei->bssid)); continue; } if (target->level < bss->level && target->level < -80) { wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR " (pref %d) does not have sufficient signal level (%d)", MAC2STR(nei->bssid), nei->preference_present ? nei->preference : -1, target->level); continue; } nei->acceptable = 1; } #ifdef CONFIG_MBO if (wpa_s->wnm_mbo_trans_reason_present) target = get_mbo_transition_candidate(wpa_s, reason); else target = get_first_acceptable(wpa_s); #else /* CONFIG_MBO */ target = get_first_acceptable(wpa_s); #endif /* CONFIG_MBO */ if (target) { wpa_printf(MSG_DEBUG, "WNM: Found an acceptable preferred transition candidate BSS " MACSTR " (RSSI %d)", MAC2STR(target->bssid), target->level); } return target; }