struct wpa_scan_results * hostapd_driver_get_scan_results(
struct hostapd_data *hapd)
{
+ if (hapd->driver && hapd->driver->get_scan_results)
+ return hapd->driver->get_scan_results(hapd->drv_priv, NULL);
if (hapd->driver && hapd->driver->get_scan_results2)
return hapd->driver->get_scan_results2(hapd->drv_priv);
return NULL;
int (*update_ft_ies)(void *priv, const u8 *md, const u8 *ies,
size_t ies_len);
+ /**
+ * get_scan_results - Fetch the latest scan results
+ * @priv: Private driver interface data
+ * @bssid: Return results only for the specified BSSID, %NULL for all
+ *
+ * Returns: Allocated buffer of scan results (caller is responsible for
+ * freeing the data structure) on success, NULL on failure
+ */
+ struct wpa_scan_results * (*get_scan_results)(void *priv,
+ const u8 *bssid);
+
/**
* get_scan_results2 - Fetch the latest scan results
* @priv: private driver interface data
.scan2 = driver_nl80211_scan2,
.sched_scan = wpa_driver_nl80211_sched_scan,
.stop_sched_scan = wpa_driver_nl80211_stop_sched_scan,
- .get_scan_results2 = wpa_driver_nl80211_get_scan_results,
+ .get_scan_results = wpa_driver_nl80211_get_scan_results,
.abort_scan = wpa_driver_nl80211_abort_scan,
.deauthenticate = driver_nl80211_deauthenticate,
.authenticate = driver_nl80211_authenticate,
int wpa_driver_nl80211_sched_scan(void *priv,
struct wpa_driver_scan_params *params);
int wpa_driver_nl80211_stop_sched_scan(void *priv);
-struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv);
+struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv,
+ const u8 *bssid);
void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv);
int wpa_driver_nl80211_abort_scan(void *priv, u64 scan_cookie);
int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
static struct wpa_scan_res *
nl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv,
- struct nl_msg *msg)
+ struct nl_msg *msg, const u8 *bssid)
{
struct nlattr *tb[NL80211_ATTR_MAX + 1];
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
bss_policy))
return NULL;
+ if (bssid && bss[NL80211_BSS_BSSID] &&
+ !ether_addr_equal(bssid, nla_data(bss[NL80211_BSS_BSSID])))
+ return NULL;
if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
struct nl80211_bss_info_arg {
struct wpa_driver_nl80211_data *drv;
struct wpa_scan_results *res;
+ const u8 *bssid;
};
static int bss_info_handler(struct nl_msg *msg, void *arg)
struct wpa_scan_res **tmp;
struct wpa_scan_res *r;
- r = nl80211_parse_bss_info(_arg->drv, msg);
+ r = nl80211_parse_bss_info(_arg->drv, msg, _arg->bssid);
if (!r)
return NL_SKIP;
static struct wpa_scan_results *
-nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv)
+nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv, const u8 *bssid)
{
struct nl_msg *msg;
struct wpa_scan_results *res;
arg.drv = drv;
arg.res = res;
+ arg.bssid = bssid;
ret = send_and_recv_resp(drv, msg, bss_info_handler, &arg);
if (ret == -EAGAIN) {
count++;
/**
* wpa_driver_nl80211_get_scan_results - Fetch the latest scan results
- * @priv: Pointer to private wext data from wpa_driver_nl80211_init()
+ * @priv: Pointer to private nl80211 data from wpa_driver_nl80211_init()
+ * @bssid: Return results only for the specified BSSID, %NULL for all
* Returns: Scan results on success, -1 on failure
*/
-struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv)
+struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv,
+ const u8 *bssid)
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
struct wpa_scan_results *res;
- res = nl80211_get_scan_results(drv);
+ res = nl80211_get_scan_results(drv, bssid);
if (res)
wpa_driver_nl80211_check_bss_status(drv, res);
return res;
struct nl80211_dump_scan_ctx *ctx = arg;
struct wpa_scan_res *r;
- r = nl80211_parse_bss_info(ctx->drv, msg);
+ r = nl80211_parse_bss_info(ctx->drv, msg, NULL);
if (!r)
return NL_SKIP;
wpa_printf(MSG_DEBUG, "nl80211: %d " MACSTR " %d%s",
}
struct wpa_scan_results *
-wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s);
+wpa_drv_get_scan_results(struct wpa_supplicant *wpa_s, const u8 *bssid);
static inline int wpa_drv_get_bssid(struct wpa_supplicant *wpa_s, u8 *bssid)
{
struct wpa_bss *bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
if (!bss) {
- wpa_supplicant_update_scan_results(wpa_s);
+ wpa_supplicant_update_scan_results(wpa_s, bssid);
/* Get the BSS from the new scan results */
bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
struct wpa_bss *bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
if (!bss) {
- wpa_supplicant_update_scan_results(wpa_s);
+ wpa_supplicant_update_scan_results(wpa_s, bssid);
bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
}
scan_res = wpa_supplicant_get_scan_results(wpa_s,
data ? &data->scan_info :
- NULL, 1);
+ NULL, 1, NULL);
if (scan_res == NULL) {
if (wpa_s->conf->ap_scan == 2 || ap ||
wpa_s->scan_res_handler == scan_only_handler)
wpa_printf(MSG_DEBUG,
"Operating frequency changed from %u to %u MHz",
wpa_s->assoc_freq, data->assoc_info.freq);
- wpa_supplicant_update_scan_results(wpa_s);
+ wpa_supplicant_update_scan_results(wpa_s, bssid);
}
}
bss = wpa_supplicant_get_new_bss(wpa_s, drv_mlo.links[i].bssid);
if (!bss) {
- wpa_supplicant_update_scan_results(wpa_s);
+ wpa_supplicant_update_scan_results(
+ wpa_s, drv_mlo.links[i].bssid);
bss = wpa_supplicant_get_new_bss(
wpa_s, drv_mlo.links[i].bssid);
}
* fetch time on the same radio so it reflects the actual time the last
* scan result event occurred.
*/
- wpa_supplicant_update_scan_results(wpa_s);
+ wpa_supplicant_update_scan_results(wpa_s, go_bssid);
dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
radio_list) {
if (ifs == wpa_s)
bss = wpa_bss_get_bssid(wpa_s, peer_addr);
if (!bss) {
- wpa_supplicant_update_scan_results(wpa_s);
+ wpa_supplicant_update_scan_results(wpa_s, peer_addr);
bss = wpa_bss_get_bssid(wpa_s, peer_addr);
if (!bss) {
wpa_printf(MSG_DEBUG, "PASN: BSS not found");
* @wpa_s: Pointer to wpa_supplicant data
* @info: Information about what was scanned or %NULL if not available
* @new_scan: Whether a new scan was performed
+ * @bssid: Return BSS entries only for a single BSSID, %NULL for all
* Returns: Scan results, %NULL on failure
*
* This function request the current scan results from the driver and updates
*/
struct wpa_scan_results *
wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
- struct scan_info *info, int new_scan)
+ struct scan_info *info, int new_scan,
+ const u8 *bssid)
{
struct wpa_scan_results *scan_res;
size_t i;
int (*compar)(const void *, const void *) = wpa_scan_result_compar;
- scan_res = wpa_drv_get_scan_results2(wpa_s);
+ scan_res = wpa_drv_get_scan_results(wpa_s, bssid);
if (scan_res == NULL) {
wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results");
return NULL;
/**
* wpa_supplicant_update_scan_results - Update scan results from the driver
* @wpa_s: Pointer to wpa_supplicant data
+ * @bssid: Update BSS entries only for a single BSSID, %NULL for all
* Returns: 0 on success, -1 on failure
*
* This function updates the BSS table within wpa_supplicant based on the
* needed information to complete the connection (e.g., to perform validation
* steps in 4-way handshake).
*/
-int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s)
+int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s,
+ const u8 *bssid)
{
struct wpa_scan_results *scan_res;
- scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
+ scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0, bssid);
if (scan_res == NULL)
return -1;
wpa_scan_results_free(scan_res);
bool default_ies, bool next);
struct wpa_scan_results *
wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
- struct scan_info *info, int new_scan);
-int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s);
+ struct scan_info *info, int new_scan,
+ const u8 *bssid);
+int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s,
+ const u8 *bssid);
const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie);
const u8 * wpa_scan_get_ml_ie(const struct wpa_scan_res *res, u8 type);
const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res,
if (!bss) {
wpa_printf(MSG_DEBUG,
"SAE: BSS not available, update scan result to get BSS");
- wpa_supplicant_update_scan_results(wpa_s);
+ wpa_supplicant_update_scan_results(wpa_s, bssid);
bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
}
if (bss) {
* It is not a new scan, this does not update the last_scan
* timestamp nor will it expire old BSSs.
*/
- wpa_supplicant_update_scan_results(wpa_s);
+ wpa_supplicant_update_scan_results(wpa_s, NULL);
if (wnm_scan_process(wpa_s, true) > 0)
return;
wpa_printf(MSG_DEBUG,
int val;
size_t i;
- res = iface->driver->get_scan_results2(iface->drv_priv);
+ if (iface->driver->get_scan_results)
+ res = iface->driver->get_scan_results(iface->drv_priv, NULL);
+ else
+ res = iface->driver->get_scan_results2(iface->drv_priv);
if (res == NULL)
goto fail;
if (iface->drv_priv == NULL)
return;
- if (iface->driver->get_scan_results2)
+ if (iface->driver->get_scan_results || iface->driver->get_scan_results2)
wpa_priv_get_scan_results2(iface, from, fromlen);
else
sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, fromlen);
struct wpa_scan_results *scan_res;
wpa_s->bgscan_ssid = wpa_s->current_ssid;
scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
- 0);
+ 0, NULL);
if (scan_res) {
bgscan_notify_scan(wpa_s, scan_res);
wpa_scan_results_free(scan_res);
if (obss_scan) {
struct wpa_scan_results *scan_res;
- scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
+ scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0,
+ NULL);
if (scan_res == NULL) {
/* Back to HT20 */
freq->sec_channel_offset = 0;
struct wpa_scan_results *
-wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
+wpa_drv_get_scan_results(struct wpa_supplicant *wpa_s, const u8 *bssid)
{
struct wpa_scan_results *scan_res;
#ifdef CONFIG_TESTING_OPTIONS
size_t idx;
#endif /* CONFIG_TESTING_OPTIONS */
- if (!wpa_s->driver->get_scan_results2)
+ if (wpa_s->driver->get_scan_results)
+ scan_res = wpa_s->driver->get_scan_results(wpa_s->drv_priv,
+ bssid);
+ else if (wpa_s->driver->get_scan_results2)
+ scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
+ else
return NULL;
- scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
#ifdef CONFIG_TESTING_OPTIONS
for (idx = 0; scan_res && idx < scan_res->num; idx++) {
/* No WPA/RSN IE found in the cached scan results. Try to get updated
* scan results from the driver. */
- if (wpa_supplicant_update_scan_results(wpa_s) < 0)
+ if (wpa_supplicant_update_scan_results(wpa_s, wpa_s->bssid) < 0)
return -1;
return wpa_get_beacon_ie(wpa_s);