aboutsummaryrefslogtreecommitdiff
path: root/wpa_supplicant/rrm.c
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2024-07-21 13:14:24 +0000
committerCy Schubert <cy@FreeBSD.org>2024-07-21 13:14:24 +0000
commit950d2f43375b87e95ebc0ecda9b281b84b2213d7 (patch)
treee5c37bef0e53ac309e9c1f0c7859da6098a18f0a /wpa_supplicant/rrm.c
parentdf0c787c3ece1d65fd6fef34aa8f56da557b5ac0 (diff)
Diffstat (limited to 'wpa_supplicant/rrm.c')
-rw-r--r--wpa_supplicant/rrm.c132
1 files changed, 94 insertions, 38 deletions
diff --git a/wpa_supplicant/rrm.c b/wpa_supplicant/rrm.c
index cf107ebaf639..2ec43105ceec 100644
--- a/wpa_supplicant/rrm.c
+++ b/wpa_supplicant/rrm.c
@@ -501,7 +501,7 @@ static int wpas_add_channel(u8 op_class, u8 chan, u8 num_primary_channels,
static int * wpas_add_channels(const struct oper_class_map *op,
- struct hostapd_hw_modes *mode, int active,
+ struct hostapd_hw_modes *mode,
const u8 *channels, const u8 size)
{
int *freqs, *next_freq;
@@ -515,6 +515,8 @@ static int * wpas_add_channels(const struct oper_class_map *op,
num_primary_channels = 4;
else if (op->bw == BW160)
num_primary_channels = 8;
+ else if (op->bw == BW320)
+ num_primary_channels = 16;
else
num_primary_channels = 1;
@@ -532,7 +534,7 @@ static int * wpas_add_channels(const struct oper_class_map *op,
enum chan_allowed res = verify_channel(mode, op->op_class, chan,
op->bw);
- if (res == NOT_ALLOWED || (res == NO_IR && active))
+ if (res == NOT_ALLOWED)
continue;
if (wpas_add_channel(op->op_class, chan, num_primary_channels,
@@ -554,13 +556,14 @@ static int * wpas_add_channels(const struct oper_class_map *op,
static int * wpas_op_class_freqs(const struct oper_class_map *op,
- struct hostapd_hw_modes *mode, int active)
+ struct hostapd_hw_modes *mode)
{
u8 channels_80mhz_5ghz[] = { 42, 58, 106, 122, 138, 155, 171 };
u8 channels_160mhz_5ghz[] = { 50, 114, 163 };
u8 channels_80mhz_6ghz[] = { 7, 23, 39, 55, 71, 87, 103, 119, 135, 151,
167, 183, 199, 215 };
u8 channels_160mhz_6ghz[] = { 15, 47, 79, 111, 143, 175, 207 };
+ u8 channels_320mhz_6ghz[] = { 31, 63, 95, 127, 159, 191 };
const u8 *channels = NULL;
size_t num_chan = 0;
bool is_6ghz = is_6ghz_op_class(op->op_class);
@@ -579,13 +582,16 @@ static int * wpas_op_class_freqs(const struct oper_class_map *op,
channels_160mhz_5ghz;
num_chan = is_6ghz ? ARRAY_SIZE(channels_160mhz_6ghz) :
ARRAY_SIZE(channels_160mhz_5ghz);
+ } else if (op->bw == BW320) {
+ channels = channels_320mhz_6ghz;
+ num_chan = ARRAY_SIZE(channels_320mhz_6ghz);
}
- return wpas_add_channels(op, mode, active, channels, num_chan);
+ return wpas_add_channels(op, mode, channels, num_chan);
}
-static int * wpas_channel_report_freqs(struct wpa_supplicant *wpa_s, int active,
+static int * wpas_channel_report_freqs(struct wpa_supplicant *wpa_s,
const char *country, const u8 *subelems,
size_t len)
{
@@ -633,7 +639,7 @@ static int * wpas_channel_report_freqs(struct wpa_supplicant *wpa_s, int active,
* by a corresponding AP Channel Report element as specified in
* IEEE Std 802.11-2016, 11.11.9.1.
*/
- new_freqs = wpas_add_channels(op, mode, active, pos, left);
+ new_freqs = wpas_add_channels(op, mode, pos, left);
if (new_freqs)
int_array_concat(&freqs, new_freqs);
@@ -648,7 +654,7 @@ out:
static int * wpas_beacon_request_freqs(struct wpa_supplicant *wpa_s,
- u8 op_class, u8 chan, int active,
+ u8 op_class, u8 chan,
const u8 *subelems, size_t len)
{
int *freqs = NULL, *ext_freqs = NULL;
@@ -678,7 +684,7 @@ static int * wpas_beacon_request_freqs(struct wpa_supplicant *wpa_s,
switch (chan) {
case 0:
- freqs = wpas_op_class_freqs(op, mode, active);
+ freqs = wpas_op_class_freqs(op, mode);
if (!freqs)
return NULL;
break;
@@ -686,14 +692,13 @@ static int * wpas_beacon_request_freqs(struct wpa_supplicant *wpa_s,
/* freqs will be added from AP channel subelements */
break;
default:
- freqs = wpas_add_channels(op, mode, active, &chan, 1);
+ freqs = wpas_add_channels(op, mode, &chan, 1);
if (!freqs)
return NULL;
break;
}
- ext_freqs = wpas_channel_report_freqs(wpa_s, active, country, subelems,
- len);
+ ext_freqs = wpas_channel_report_freqs(wpa_s, country, subelems, len);
if (ext_freqs) {
int_array_concat(&freqs, ext_freqs);
os_free(ext_freqs);
@@ -732,24 +737,24 @@ int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len,
vht_oper = (struct ieee80211_vht_operation *) (ie + 2);
switch (vht_oper->vht_op_info_chwidth) {
- case 1:
+ case CHANWIDTH_80MHZ:
seg0 = vht_oper->vht_op_info_chan_center_freq_seg0_idx;
seg1 = vht_oper->vht_op_info_chan_center_freq_seg1_idx;
if (seg1 && abs(seg1 - seg0) == 8)
- vht = CHANWIDTH_160MHZ;
+ vht = CONF_OPER_CHWIDTH_160MHZ;
else if (seg1)
- vht = CHANWIDTH_80P80MHZ;
+ vht = CONF_OPER_CHWIDTH_80P80MHZ;
else
- vht = CHANWIDTH_80MHZ;
+ vht = CONF_OPER_CHWIDTH_80MHZ;
break;
- case 2:
- vht = CHANWIDTH_160MHZ;
+ case CHANWIDTH_160MHZ:
+ vht = CONF_OPER_CHWIDTH_160MHZ;
break;
- case 3:
- vht = CHANWIDTH_80P80MHZ;
+ case CHANWIDTH_80P80MHZ:
+ vht = CONF_OPER_CHWIDTH_80P80MHZ;
break;
default:
- vht = CHANWIDTH_USE_HT;
+ vht = CONF_OPER_CHWIDTH_USE_HT;
break;
}
}
@@ -773,6 +778,7 @@ int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len,
static int wpas_beacon_rep_add_frame_body(struct bitfield *eids,
+ struct bitfield *ext_eids,
enum beacon_report_detail detail,
struct wpa_bss *bss, u8 *buf,
size_t buf_len, const u8 **ies_buf,
@@ -829,7 +835,9 @@ static int wpas_beacon_rep_add_frame_body(struct bitfield *eids,
*/
while (ies_len > 2 && 2U + ies[1] <= ies_len && rem_len > 0) {
if (detail == BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS ||
- (eids && bitfield_is_set(eids, ies[0]))) {
+ (eids && bitfield_is_set(eids, ies[0])) ||
+ (ext_eids && ies[0] == WLAN_EID_EXTENSION && ies[1] &&
+ bitfield_is_set(ext_eids, ies[2]))) {
u8 elen = ies[1];
if (2 + elen > buf + buf_len - pos ||
@@ -877,7 +885,8 @@ static int wpas_add_beacon_rep_elem(struct beacon_rep_data *data,
os_memcpy(buf, rep, sizeof(*rep));
- ret = wpas_beacon_rep_add_frame_body(data->eids, data->report_detail,
+ ret = wpas_beacon_rep_add_frame_body(data->eids, data->ext_eids,
+ data->report_detail,
bss, buf + sizeof(*rep),
14 + *ie_len, ie, ie_len,
idx == 0);
@@ -933,8 +942,8 @@ static int wpas_add_beacon_rep(struct wpa_supplicant *wpa_s,
struct rrm_measurement_beacon_report rep;
u8 idx = 0;
- if (os_memcmp(data->bssid, broadcast_ether_addr, ETH_ALEN) != 0 &&
- os_memcmp(data->bssid, bss->bssid, ETH_ALEN) != 0)
+ if (!ether_addr_equal(data->bssid, broadcast_ether_addr) &&
+ !ether_addr_equal(data->bssid, bss->bssid))
return 0;
if (data->ssid_len &&
@@ -1034,7 +1043,7 @@ static void wpas_rrm_scan_timeout(void *eloop_ctx, void *timeout_ctx)
}
os_get_reltime(&wpa_s->beacon_rep_scan);
if (wpa_s->scanning || wpas_p2p_in_progress(wpa_s) ||
- wpa_supplicant_trigger_scan(wpa_s, params))
+ wpa_supplicant_trigger_scan(wpa_s, params, true, false))
wpas_rrm_refuse_request(wpa_s);
params->duration = prev_duration;
}
@@ -1044,6 +1053,7 @@ static int wpas_rm_handle_beacon_req_subelem(struct wpa_supplicant *wpa_s,
struct beacon_rep_data *data,
u8 sid, u8 slen, const u8 *subelem)
{
+ struct bitfield *eids;
u8 report_info, i;
switch (sid) {
@@ -1097,6 +1107,7 @@ static int wpas_rm_handle_beacon_req_subelem(struct wpa_supplicant *wpa_s,
break;
case WLAN_BEACON_REQUEST_SUBELEM_REQUEST:
+ case WLAN_BEACON_REQUEST_SUBELEM_EXT_REQUEST:
if (data->report_detail !=
BEACON_REPORT_DETAIL_REQUESTED_ONLY) {
wpa_printf(MSG_DEBUG,
@@ -1112,20 +1123,46 @@ static int wpas_rm_handle_beacon_req_subelem(struct wpa_supplicant *wpa_s,
return -1;
}
- if (data->eids) {
+ if (sid == WLAN_BEACON_REQUEST_SUBELEM_EXT_REQUEST) {
+ if (slen < 2) {
+ wpa_printf(MSG_DEBUG,
+ "Invalid extended request");
+ return -1;
+ }
+ if (subelem[0] != WLAN_EID_EXTENSION) {
+ wpa_printf(MSG_DEBUG,
+ "Skip unknown Requested Element ID %u in Extended Request subelement",
+ subelem[0]);
+ break;
+ }
+
+ /* Skip the Requested Element ID field */
+ subelem++;
+ slen--;
+ }
+
+ if ((sid == WLAN_BEACON_REQUEST_SUBELEM_REQUEST &&
+ data->eids) ||
+ (sid == WLAN_BEACON_REQUEST_SUBELEM_EXT_REQUEST &&
+ data->ext_eids)) {
wpa_printf(MSG_DEBUG,
- "Beacon Request: Request subelement appears more than once");
+ "Beacon Request: Request sub elements appear more than once");
return -1;
}
- data->eids = bitfield_alloc(255);
- if (!data->eids) {
+ eids = bitfield_alloc(255);
+ if (!eids) {
wpa_printf(MSG_DEBUG, "Failed to allocate EIDs bitmap");
return -1;
}
+ if (sid == WLAN_BEACON_REQUEST_SUBELEM_REQUEST)
+ data->eids = eids;
+ else
+ data->ext_eids = eids;
+
for (i = 0; i < slen; i++)
- bitfield_set(data->eids, subelem[i]);
+ bitfield_set(eids, subelem[i]);
break;
case WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL:
/* Skip - it will be processed when freqs are added */
@@ -1220,10 +1257,9 @@ wpas_rm_handle_beacon_req(struct wpa_supplicant *wpa_s,
goto out;
}
- params->freqs = wpas_beacon_request_freqs(
- wpa_s, req->oper_class, req->channel,
- req->mode == BEACON_REPORT_MODE_ACTIVE,
- req->variable, len - sizeof(*req));
+ params->freqs = wpas_beacon_request_freqs(wpa_s, req->oper_class,
+ req->channel, req->variable,
+ len - sizeof(*req));
if (!params->freqs) {
wpa_printf(MSG_DEBUG, "Beacon request: No valid channels");
reject_mode = MEASUREMENT_REPORT_MODE_REJECT_REFUSED;
@@ -1482,6 +1518,26 @@ void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
}
+static bool wpas_beacon_rep_scan_match(struct wpa_supplicant *wpa_s,
+ const u8 *bssid)
+{
+ u8 i;
+
+ if (!wpa_s->valid_links)
+ return ether_addr_equal(wpa_s->current_bss->bssid, bssid);
+
+ for_each_link(wpa_s->valid_links, i) {
+ if (ether_addr_equal(wpa_s->links[i].bssid, bssid))
+ return true;
+ }
+
+ wpa_printf(MSG_DEBUG, "RRM: MLD: no match for TSF BSSID=" MACSTR,
+ MAC2STR(bssid));
+
+ return false;
+}
+
+
int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res,
struct scan_info *info)
@@ -1503,8 +1559,7 @@ int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s,
MAC2STR(info->scan_start_tsf_bssid),
MAC2STR(wpa_s->current_bss->bssid));
if ((wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT) &&
- os_memcmp(info->scan_start_tsf_bssid, wpa_s->current_bss->bssid,
- ETH_ALEN) != 0) {
+ !wpas_beacon_rep_scan_match(wpa_s, info->scan_start_tsf_bssid)) {
wpa_printf(MSG_DEBUG,
"RRM: Ignore scan results due to mismatching TSF BSSID");
goto out;
@@ -1519,8 +1574,8 @@ int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s,
if ((wpa_s->drv_rrm_flags &
WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT) &&
- os_memcmp(scan_res->res[i]->tsf_bssid,
- wpa_s->current_bss->bssid, ETH_ALEN) != 0) {
+ !wpas_beacon_rep_scan_match(wpa_s,
+ scan_res->res[i]->tsf_bssid)) {
wpa_printf(MSG_DEBUG,
"RRM: Ignore scan result for " MACSTR
" due to mismatching TSF BSSID" MACSTR,
@@ -1589,6 +1644,7 @@ void wpas_clear_beacon_rep_data(struct wpa_supplicant *wpa_s)
eloop_cancel_timeout(wpas_rrm_scan_timeout, wpa_s, NULL);
bitfield_free(data->eids);
+ bitfield_free(data->ext_eids);
os_free(data->scan_params.freqs);
os_memset(data, 0, sizeof(*data));
}