aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--wpa_supplicant/wnm_sta.c85
-rw-r--r--wpa_supplicant/wnm_sta.h1
-rw-r--r--wpa_supplicant/wpa_supplicant.c2
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h1
4 files changed, 86 insertions, 3 deletions
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index b64a411..7aa2f7f 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -10,6 +10,7 @@
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
#include "common/wpa_ctrl.h"
#include "rsn_supp/wpa.h"
#include "wpa_supplicant_i.h"
@@ -406,6 +407,12 @@ static void wnm_parse_neighbor_report_elem(struct neighbor_report *rep,
}
+static int wnm_nei_get_chan(struct wpa_supplicant *wpa_s, u8 op_class, u8 chan)
+{
+ return ieee80211_chan_to_freq(NULL, op_class, chan);
+}
+
+
static void wnm_parse_neighbor_report(struct wpa_supplicant *wpa_s,
const u8 *pos, u8 len,
struct neighbor_report *rep)
@@ -442,6 +449,9 @@ static void wnm_parse_neighbor_report(struct wpa_supplicant *wpa_s,
left -= elen;
pos += elen;
}
+
+ rep->freq = wnm_nei_get_chan(wpa_s, rep->regulatory_class,
+ rep->channel_number);
}
@@ -673,12 +683,82 @@ static void wnm_dump_cand_list(struct wpa_supplicant *wpa_s)
nei = &wpa_s->wnm_neighbor_report_elements[i];
wpa_printf(MSG_DEBUG, "%u: " MACSTR
- " info=0x%x op_class=%u chan=%u phy=%u pref=%d",
+ " info=0x%x op_class=%u chan=%u phy=%u pref=%d freq=%d",
i, MAC2STR(nei->bssid), nei->bssid_info,
nei->regulatory_class,
nei->channel_number, nei->phy_type,
- nei->preference_present ? nei->preference : -1);
+ nei->preference_present ? nei->preference : -1,
+ nei->freq);
+ }
+}
+
+
+static int chan_supported(struct wpa_supplicant *wpa_s, int freq)
+{
+ unsigned int i;
+
+ for (i = 0; i < wpa_s->hw.num_modes; i++) {
+ struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
+ int j;
+
+ for (j = 0; j < mode->num_channels; j++) {
+ struct hostapd_channel_data *chan;
+
+ chan = &mode->channels[j];
+ if (chan->freq == freq &&
+ !(chan->flag & HOSTAPD_CHAN_DISABLED))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+static void wnm_set_scan_freqs(struct wpa_supplicant *wpa_s)
+{
+ int *freqs;
+ int num_freqs = 0;
+ unsigned int i;
+
+ if (!wpa_s->wnm_neighbor_report_elements)
+ return;
+
+ if (wpa_s->hw.modes == NULL)
+ return;
+
+ os_free(wpa_s->next_scan_freqs);
+ wpa_s->next_scan_freqs = NULL;
+
+ freqs = os_calloc(wpa_s->wnm_num_neighbor_report + 1, sizeof(int));
+ if (freqs == NULL)
+ return;
+
+ 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->freq <= 0) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Unknown neighbor operating frequency for "
+ MACSTR " - scan all channels",
+ MAC2STR(nei->bssid));
+ os_free(freqs);
+ return;
+ }
+ if (chan_supported(wpa_s, nei->freq))
+ add_freq(freqs, &num_freqs, nei->freq);
}
+
+ if (num_freqs == 0) {
+ os_free(freqs);
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "WNM: Scan %d frequencies based on transition candidate list",
+ num_freqs);
+ wpa_s->next_scan_freqs = freqs;
}
@@ -794,6 +874,7 @@ static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s,
wpa_s->wnm_cand_valid_until.usec %= 1000000;
os_memcpy(wpa_s->wnm_cand_from_bss, wpa_s->bssid, ETH_ALEN);
+ wnm_set_scan_freqs(wpa_s);
wpa_supplicant_req_scan(wpa_s, 0, 0);
} else if (reply) {
enum bss_trans_mgmt_status_code status;
diff --git a/wpa_supplicant/wnm_sta.h b/wpa_supplicant/wnm_sta.h
index a45a695..fd3a5dd 100644
--- a/wpa_supplicant/wnm_sta.h
+++ b/wpa_supplicant/wnm_sta.h
@@ -45,6 +45,7 @@ struct neighbor_report {
unsigned int bss_term_present:1;
struct measurement_pilot *meas_pilot;
struct multiple_bssid *mul_bssid;
+ int freq;
};
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 8261c66..aeed3a8 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -4402,7 +4402,7 @@ void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
}
-static void add_freq(int *freqs, int *num_freqs, int freq)
+void add_freq(int *freqs, int *num_freqs, int freq)
{
int i;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index a9f5d17..e52dfd9 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -992,6 +992,7 @@ void wpas_request_connection(struct wpa_supplicant *wpa_s);
int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen);
int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style);
int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s);
+void add_freq(int *freqs, int *num_freqs, int freq);
/**
* wpa_supplicant_ctrl_iface_ctrl_rsp_handle - Handle a control response