diff options
| author | Cy Schubert <cy@FreeBSD.org> | 2024-07-21 13:14:24 +0000 |
|---|---|---|
| committer | Cy Schubert <cy@FreeBSD.org> | 2024-07-21 13:14:24 +0000 |
| commit | 950d2f43375b87e95ebc0ecda9b281b84b2213d7 (patch) | |
| tree | e5c37bef0e53ac309e9c1f0c7859da6098a18f0a /wpa_supplicant/rrm.c | |
| parent | df0c787c3ece1d65fd6fef34aa8f56da557b5ac0 (diff) | |
Diffstat (limited to 'wpa_supplicant/rrm.c')
| -rw-r--r-- | wpa_supplicant/rrm.c | 132 |
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)); } |
