wpa_supplicant: Remove duplicate logic in wpas_ml_element()
Parsing multiple RNR elements already exists in wpa_bss_parse_basic_ml_element(), so wpas_ml_element() just duplicates the same code. Combine the functionality of both these functions and remove the duplicate. Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
This commit is contained in:
parent
74b6884306
commit
cb90aa3acf
6 changed files with 76 additions and 276 deletions
|
@ -2495,35 +2495,6 @@ const u8 * get_ie(const u8 *ies, size_t len, u8 eid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get_ie_nth - Fetch a specified information element from IEs buffer
|
|
||||||
* @ies: Information elements buffer
|
|
||||||
* @len: Information elements buffer length
|
|
||||||
* @eid: Information element identifier (WLAN_EID_*)
|
|
||||||
* @nth: Return the nth element of the requested type (2 returns the second)
|
|
||||||
* Returns: Pointer to the information element (id field) or %NULL if not found
|
|
||||||
*
|
|
||||||
* This function returns the nth matching information element in the IEs
|
|
||||||
* buffer or %NULL in case the element is not found.
|
|
||||||
*/
|
|
||||||
const u8 * get_ie_nth(const u8 *ies, size_t len, u8 eid, int nth)
|
|
||||||
{
|
|
||||||
const struct element *elem;
|
|
||||||
int sofar = 0;
|
|
||||||
|
|
||||||
if (!ies)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for_each_element_id(elem, eid, ies, len) {
|
|
||||||
sofar++;
|
|
||||||
if (sofar == nth)
|
|
||||||
return &elem->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get_ie_ext - Fetch a specified extended information element from IEs buffer
|
* get_ie_ext - Fetch a specified extended information element from IEs buffer
|
||||||
* @ies: Information elements buffer
|
* @ies: Information elements buffer
|
||||||
|
|
|
@ -261,7 +261,6 @@ extern const struct oper_class_map global_op_class[];
|
||||||
extern size_t global_op_class_size;
|
extern size_t global_op_class_size;
|
||||||
|
|
||||||
const u8 * get_ie(const u8 *ies, size_t len, u8 eid);
|
const u8 * get_ie(const u8 *ies, size_t len, u8 eid);
|
||||||
const u8 * get_ie_nth(const u8 *ies, size_t len, u8 eid, int nth);
|
|
||||||
const u8 * get_ie_ext(const u8 *ies, size_t len, u8 ext);
|
const u8 * get_ie_ext(const u8 *ies, size_t len, u8 ext);
|
||||||
const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type);
|
const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "common/ieee802_11_defs.h"
|
#include "common/ieee802_11_defs.h"
|
||||||
#include "drivers/driver.h"
|
#include "drivers/driver.h"
|
||||||
#include "eap_peer/eap.h"
|
#include "eap_peer/eap.h"
|
||||||
|
#include "rsn_supp/wpa.h"
|
||||||
#include "wpa_supplicant_i.h"
|
#include "wpa_supplicant_i.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "notify.h"
|
#include "notify.h"
|
||||||
|
@ -1222,22 +1223,6 @@ const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* wpa_bss_get_ie_nth - Fetch a specified information element from a BSS entry
|
|
||||||
* @bss: BSS table entry
|
|
||||||
* @ie: Information element identitifier (WLAN_EID_*)
|
|
||||||
* @nth: Return the nth element of the requested type (2 returns the second)
|
|
||||||
* Returns: Pointer to the information element (id field) or %NULL if not found
|
|
||||||
*
|
|
||||||
* This function returns the nth matching information element in the BSS
|
|
||||||
* entry.
|
|
||||||
*/
|
|
||||||
const u8 * wpa_bss_get_ie_nth(const struct wpa_bss *bss, u8 ie, int nth)
|
|
||||||
{
|
|
||||||
return get_ie_nth(wpa_bss_ie_ptr(bss), bss->ie_len, ie, nth);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wpa_bss_get_ie_ext - Fetch a specified extended IE from a BSS entry
|
* wpa_bss_get_ie_ext - Fetch a specified extended IE from a BSS entry
|
||||||
* @bss: BSS table entry
|
* @bss: BSS table entry
|
||||||
|
@ -1501,7 +1486,8 @@ static void
|
||||||
wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
|
wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_bss *bss, u8 mbssid_idx,
|
struct wpa_bss *bss, u8 mbssid_idx,
|
||||||
const struct ieee80211_neighbor_ap_info *ap_info,
|
const struct ieee80211_neighbor_ap_info *ap_info,
|
||||||
size_t len, u16 *seen, u16 *missing)
|
size_t len, u16 *seen, u16 *missing,
|
||||||
|
struct wpa_ssid *ssid)
|
||||||
{
|
{
|
||||||
const u8 *pos, *end;
|
const u8 *pos, *end;
|
||||||
const u8 *mld_params;
|
const u8 *mld_params;
|
||||||
|
@ -1525,12 +1511,15 @@ wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
|
||||||
pos += sizeof(*ap_info);
|
pos += sizeof(*ap_info);
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
|
u8 bss_params;
|
||||||
|
|
||||||
if (bss->n_mld_links >= MAX_NUM_MLD_LINKS)
|
if (bss->n_mld_links >= MAX_NUM_MLD_LINKS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (end - pos < ap_info->tbtt_info_len)
|
if (end - pos < ap_info->tbtt_info_len)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
bss_params = pos[1 + ETH_ALEN + 4];
|
||||||
mld_params = pos + mld_params_offset;
|
mld_params = pos + mld_params_offset;
|
||||||
|
|
||||||
link_id = *(mld_params + 1) & EHT_ML_LINK_ID_MSK;
|
link_id = *(mld_params + 1) & EHT_ML_LINK_ID_MSK;
|
||||||
|
@ -1546,7 +1535,13 @@ wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
|
||||||
wpa_printf(MSG_DEBUG, "MLD: mld ID=%u, link ID=%u",
|
wpa_printf(MSG_DEBUG, "MLD: mld ID=%u, link ID=%u",
|
||||||
*mld_params, link_id);
|
*mld_params, link_id);
|
||||||
|
|
||||||
if (neigh_bss) {
|
if (!neigh_bss) {
|
||||||
|
*missing |= BIT(link_id);
|
||||||
|
} else if (!ssid ||
|
||||||
|
(bss_params & (RNR_BSS_PARAM_SAME_SSID |
|
||||||
|
RNR_BSS_PARAM_CO_LOCATED)) ||
|
||||||
|
wpa_scan_res_match(wpa_s, 0, neigh_bss,
|
||||||
|
ssid, 1, 0)) {
|
||||||
struct mld_link *l;
|
struct mld_link *l;
|
||||||
|
|
||||||
l = &bss->mld_links[bss->n_mld_links];
|
l = &bss->mld_links[bss->n_mld_links];
|
||||||
|
@ -1555,8 +1550,6 @@ wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
|
||||||
ETH_ALEN);
|
ETH_ALEN);
|
||||||
l->freq = neigh_bss->freq;
|
l->freq = neigh_bss->freq;
|
||||||
bss->n_mld_links++;
|
bss->n_mld_links++;
|
||||||
} else {
|
|
||||||
*missing |= BIT(link_id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1573,6 +1566,7 @@ wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
|
||||||
* @link_info: Array to store link information (or %NULL),
|
* @link_info: Array to store link information (or %NULL),
|
||||||
* should be initialized and #MAX_NUM_MLD_LINKS elements long
|
* should be initialized and #MAX_NUM_MLD_LINKS elements long
|
||||||
* @missing_links: Result bitmask of links that were not discovered (or %NULL)
|
* @missing_links: Result bitmask of links that were not discovered (or %NULL)
|
||||||
|
* @ssid: Target SSID (or %NULL)
|
||||||
* Returns: 0 on success or -1 for non-MLD or parsing failures
|
* Returns: 0 on success or -1 for non-MLD or parsing failures
|
||||||
*
|
*
|
||||||
* Parses the Basic Multi-Link element of the BSS into @link_info using the scan
|
* Parses the Basic Multi-Link element of the BSS into @link_info using the scan
|
||||||
|
@ -1583,7 +1577,8 @@ wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
|
||||||
int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
|
int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_bss *bss,
|
struct wpa_bss *bss,
|
||||||
u8 *ap_mld_addr,
|
u8 *ap_mld_addr,
|
||||||
u16 *missing_links)
|
u16 *missing_links,
|
||||||
|
struct wpa_ssid *ssid)
|
||||||
{
|
{
|
||||||
struct ieee802_11_elems elems;
|
struct ieee802_11_elems elems;
|
||||||
struct wpabuf *mlbuf;
|
struct wpabuf *mlbuf;
|
||||||
|
@ -1624,6 +1619,32 @@ int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
|
||||||
|
|
||||||
ml_ie_len = wpabuf_len(mlbuf);
|
ml_ie_len = wpabuf_len(mlbuf);
|
||||||
|
|
||||||
|
if (ssid) {
|
||||||
|
struct wpa_ie_data ie;
|
||||||
|
|
||||||
|
if (!elems.rsn_ie ||
|
||||||
|
wpa_parse_wpa_ie(elems.rsn_ie - 2, 2 + elems.rsn_ie_len,
|
||||||
|
&ie)) {
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RSN element");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ie.capabilities & WPA_CAPABILITY_MFPC) ||
|
||||||
|
wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION) {
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG,
|
||||||
|
"MLD: No management frame protection");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ie.key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK |
|
||||||
|
WPA_KEY_MGMT_PSK_SHA256);
|
||||||
|
if (!(ie.key_mgmt & ssid->key_mgmt)) {
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG,
|
||||||
|
"MLD: No valid key management");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* for ext ID + 2 control + common info len + MLD address +
|
* for ext ID + 2 control + common info len + MLD address +
|
||||||
* link info
|
* link info
|
||||||
|
@ -1703,7 +1724,7 @@ int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
|
||||||
|
|
||||||
wpa_bss_parse_ml_rnr_ap_info(wpa_s, bss, mbssid_idx,
|
wpa_bss_parse_ml_rnr_ap_info(wpa_s, bss, mbssid_idx,
|
||||||
ap_info, len, &seen,
|
ap_info, len, &seen,
|
||||||
&missing);
|
&missing, ssid);
|
||||||
|
|
||||||
pos += ap_info_len;
|
pos += ap_info_len;
|
||||||
len -= ap_info_len;
|
len -= ap_info_len;
|
||||||
|
|
|
@ -171,7 +171,6 @@ struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id);
|
||||||
struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s,
|
struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s,
|
||||||
unsigned int idf, unsigned int idl);
|
unsigned int idf, unsigned int idl);
|
||||||
const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie);
|
const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie);
|
||||||
const u8 * wpa_bss_get_ie_nth(const struct wpa_bss *bss, u8 ie, int nth);
|
|
||||||
const u8 * wpa_bss_get_ie_ext(const struct wpa_bss *bss, u8 ext);
|
const u8 * wpa_bss_get_ie_ext(const struct wpa_bss *bss, u8 ext);
|
||||||
const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type);
|
const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type);
|
||||||
const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss,
|
const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss,
|
||||||
|
@ -216,7 +215,8 @@ void calculate_update_time(const struct os_reltime *fetch_time,
|
||||||
int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
|
int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_bss *bss,
|
struct wpa_bss *bss,
|
||||||
u8 *ap_mld_addr,
|
u8 *ap_mld_addr,
|
||||||
u16 *missing_links);
|
u16 *missing_links,
|
||||||
|
struct wpa_ssid *ssid);
|
||||||
u16 wpa_bss_parse_reconf_ml_element(struct wpa_supplicant *wpa_s,
|
u16 wpa_bss_parse_reconf_ml_element(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_bss *bss);
|
struct wpa_bss *bss);
|
||||||
|
|
||||||
|
|
|
@ -1153,7 +1153,7 @@ static bool wpas_valid_ml_bss(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
|
||||||
{
|
{
|
||||||
u16 removed_links;
|
u16 removed_links;
|
||||||
|
|
||||||
if (wpa_bss_parse_basic_ml_element(wpa_s, bss, NULL, NULL))
|
if (wpa_bss_parse_basic_ml_element(wpa_s, bss, NULL, NULL, NULL))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (bss->n_mld_links == 0)
|
if (bss->n_mld_links == 0)
|
||||||
|
@ -1878,7 +1878,8 @@ static int wpa_supplicant_connect_ml_missing(struct wpa_supplicant *wpa_s,
|
||||||
|
|
||||||
/* Try to resolve any missing link information */
|
/* Try to resolve any missing link information */
|
||||||
if (wpa_bss_parse_basic_ml_element(wpa_s, selected, NULL,
|
if (wpa_bss_parse_basic_ml_element(wpa_s, selected, NULL,
|
||||||
&missing_links) || !missing_links)
|
&missing_links, ssid) ||
|
||||||
|
!missing_links)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
removed_links = wpa_bss_parse_reconf_ml_element(wpa_s, selected);
|
removed_links = wpa_bss_parse_reconf_ml_element(wpa_s, selected);
|
||||||
|
|
|
@ -378,225 +378,6 @@ static void sme_auth_handle_rrm(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void wpas_process_tbtt_info(struct wpa_supplicant *wpa_s, const u8 *data)
|
|
||||||
{
|
|
||||||
struct wpa_bss *neigh_bss;
|
|
||||||
const u8 *bssid;
|
|
||||||
u8 bss_params;
|
|
||||||
u8 link_id;
|
|
||||||
|
|
||||||
/* TBTT Information field
|
|
||||||
* Neighbor AP TBTT Offset[1]
|
|
||||||
* BSSID[6]
|
|
||||||
* Short SSID[4]
|
|
||||||
* BSS parameters[1]
|
|
||||||
* 20 MHz PSD[1]
|
|
||||||
* MLD Parameters[3]
|
|
||||||
* B0..B7: AP MLD ID
|
|
||||||
* B7..B11: Link ID
|
|
||||||
* B12..B19: BSS Parameters Change Count
|
|
||||||
* B20: All Updates Included
|
|
||||||
* B21: Disabled Link Indication */
|
|
||||||
|
|
||||||
bssid = data + 1;
|
|
||||||
bss_params = data[1 + ETH_ALEN + 4];
|
|
||||||
|
|
||||||
data += 13; /* MLD Parameters */
|
|
||||||
link_id = *(data + 1) & 0xF;
|
|
||||||
|
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG,
|
|
||||||
"MLD: mld ID=%u, link ID=%u, bssid=" MACSTR ", bss_params=0x%x",
|
|
||||||
*data, link_id, MAC2STR(bssid), bss_params);
|
|
||||||
|
|
||||||
if (*data) {
|
|
||||||
wpa_printf(MSG_DEBUG, "MLD: Reported link not part of MLD");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
neigh_bss = wpa_bss_get_bssid(wpa_s, bssid);
|
|
||||||
if (!neigh_bss) {
|
|
||||||
wpa_printf(MSG_DEBUG, "MLD: Neighbor not found in scan");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!((bss_params & RNR_BSS_PARAM_SAME_SSID) &&
|
|
||||||
(bss_params & RNR_BSS_PARAM_CO_LOCATED)) &&
|
|
||||||
!wpa_scan_res_match(wpa_s, 0, neigh_bss, wpa_s->current_ssid,
|
|
||||||
1, 0)) {
|
|
||||||
wpa_printf(MSG_DEBUG,
|
|
||||||
"MLD: Neighbor doesn't match current SSID - skip link");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wpa_s->valid_links |= BIT(link_id);
|
|
||||||
os_memcpy(wpa_s->links[link_id].bssid, bssid, ETH_ALEN);
|
|
||||||
wpa_s->links[link_id].freq = neigh_bss->freq;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void wpas_process_rnr(struct wpa_supplicant *wpa_s, const u8 *pos,
|
|
||||||
size_t rnr_ie_len)
|
|
||||||
{
|
|
||||||
while (rnr_ie_len > sizeof(struct ieee80211_neighbor_ap_info)) {
|
|
||||||
const struct ieee80211_neighbor_ap_info *ap_info =
|
|
||||||
(const struct ieee80211_neighbor_ap_info *) pos;
|
|
||||||
/* The first TBTT Information field */
|
|
||||||
const u8 *data = ap_info->data;
|
|
||||||
u8 tbtt_count;
|
|
||||||
size_t len;
|
|
||||||
int tbtt_i;
|
|
||||||
|
|
||||||
if (rnr_ie_len < sizeof(struct ieee80211_neighbor_ap_info))
|
|
||||||
break;
|
|
||||||
|
|
||||||
tbtt_count = (ap_info->tbtt_info_hdr >> 4) + 1;
|
|
||||||
len = sizeof(struct ieee80211_neighbor_ap_info) +
|
|
||||||
ap_info->tbtt_info_len * tbtt_count;
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "MLD: op_class=%u, channel=%u",
|
|
||||||
ap_info->op_class, ap_info->channel);
|
|
||||||
|
|
||||||
if (len > rnr_ie_len)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (ap_info->tbtt_info_len < 16) {
|
|
||||||
rnr_ie_len -= len;
|
|
||||||
pos += len;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (tbtt_i = 0; tbtt_i < tbtt_count; tbtt_i++) {
|
|
||||||
wpas_process_tbtt_info(wpa_s, data);
|
|
||||||
data += ap_info->tbtt_info_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
rnr_ie_len -= len;
|
|
||||||
pos += len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool wpas_ml_element(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
|
|
||||||
struct wpa_ssid *ssid)
|
|
||||||
{
|
|
||||||
struct wpabuf *mlbuf;
|
|
||||||
const u8 *rnr_ie, *rsn_ie;
|
|
||||||
struct wpa_ie_data ie;
|
|
||||||
u8 ml_ie_len;
|
|
||||||
const struct ieee80211_eht_ml *eht_ml;
|
|
||||||
const struct eht_ml_basic_common_info *ml_basic_common_info;
|
|
||||||
struct ieee802_11_elems elems;
|
|
||||||
u8 i;
|
|
||||||
const u16 control =
|
|
||||||
host_to_le16(MULTI_LINK_CONTROL_TYPE_BASIC |
|
|
||||||
BASIC_MULTI_LINK_CTRL_PRES_LINK_ID |
|
|
||||||
BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT |
|
|
||||||
BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA);
|
|
||||||
bool ret = false;
|
|
||||||
int rnr_idx;
|
|
||||||
|
|
||||||
if (!(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (ieee802_11_parse_elems(wpa_bss_ie_ptr(bss),
|
|
||||||
bss->ie_len, &elems, 1) == ParseFailed)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
mlbuf = ieee802_11_defrag(elems.basic_mle, elems.basic_mle_len, true);
|
|
||||||
if (!mlbuf) {
|
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No ML element");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
|
|
||||||
if (!rsn_ie || wpa_parse_wpa_ie(rsn_ie, 2 + rsn_ie[1], &ie)) {
|
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RSN element");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(ie.capabilities & WPA_CAPABILITY_MFPC) ||
|
|
||||||
wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION) {
|
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG,
|
|
||||||
"MLD: No management frame protection");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ie.key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK |
|
|
||||||
WPA_KEY_MGMT_PSK_SHA256);
|
|
||||||
if (!(ie.key_mgmt & ssid->key_mgmt)) {
|
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No valid key management");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ml_ie_len = wpabuf_len(mlbuf);
|
|
||||||
|
|
||||||
/* control + common info len + MLD address + MLD link information */
|
|
||||||
if (ml_ie_len < 2 + 1 + ETH_ALEN + 1)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
eht_ml = wpabuf_head(mlbuf);
|
|
||||||
if ((eht_ml->ml_control & control) != control) {
|
|
||||||
wpa_printf(MSG_DEBUG, "MLD: Unexpected ML element control=0x%x",
|
|
||||||
eht_ml->ml_control);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ml_basic_common_info =
|
|
||||||
(const struct eht_ml_basic_common_info *) eht_ml->variable;
|
|
||||||
|
|
||||||
/* common info length should be valid (self, mld_addr, link_id) */
|
|
||||||
if (ml_basic_common_info->len < 1 + ETH_ALEN + 1)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* get the MLD address and MLD link ID */
|
|
||||||
os_memcpy(wpa_s->ap_mld_addr, ml_basic_common_info->mld_addr,
|
|
||||||
ETH_ALEN);
|
|
||||||
wpa_s->mlo_assoc_link_id = ml_basic_common_info->variable[0] &
|
|
||||||
EHT_ML_LINK_ID_MSK;
|
|
||||||
|
|
||||||
os_memcpy(wpa_s->links[wpa_s->mlo_assoc_link_id].bssid, bss->bssid,
|
|
||||||
ETH_ALEN);
|
|
||||||
wpa_s->links[wpa_s->mlo_assoc_link_id].freq = bss->freq;
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "MLD: address=" MACSTR ", link ID=%u",
|
|
||||||
MAC2STR(wpa_s->ap_mld_addr), wpa_s->mlo_assoc_link_id);
|
|
||||||
|
|
||||||
wpa_s->valid_links = BIT(wpa_s->mlo_assoc_link_id);
|
|
||||||
|
|
||||||
ret = true;
|
|
||||||
|
|
||||||
/* Process all Reduced Neighbor Report elements */
|
|
||||||
for (rnr_idx = 1; ; rnr_idx++) {
|
|
||||||
rnr_ie = wpa_bss_get_ie_nth(bss,
|
|
||||||
WLAN_EID_REDUCED_NEIGHBOR_REPORT,
|
|
||||||
rnr_idx);
|
|
||||||
if (!rnr_ie) {
|
|
||||||
if (rnr_idx == 0) {
|
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG,
|
|
||||||
"MLD: No RNR element");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
wpas_process_rnr(wpa_s, rnr_ie + 2, rnr_ie[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "MLD: valid_links=0x%x", wpa_s->valid_links);
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
|
|
||||||
if (!(wpa_s->valid_links & BIT(i)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "MLD: link=%u, bssid=" MACSTR,
|
|
||||||
i, MAC2STR(wpa_s->links[i].bssid));
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
wpabuf_free(mlbuf);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void wpas_ml_handle_removed_links(struct wpa_supplicant *wpa_s,
|
static void wpas_ml_handle_removed_links(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_bss *bss)
|
struct wpa_bss *bss)
|
||||||
{
|
{
|
||||||
|
@ -737,6 +518,27 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpas_sme_set_mlo_links(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_bss *bss)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
wpa_s->valid_links = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < bss->n_mld_links; i++) {
|
||||||
|
u8 link_id = bss->mld_links[i].link_id;
|
||||||
|
const u8 *bssid = bss->mld_links[i].bssid;
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
wpa_s->mlo_assoc_link_id = link_id;
|
||||||
|
wpa_s->valid_links |= BIT(link_id);
|
||||||
|
os_memcpy(wpa_s->links[link_id].bssid, bssid, ETH_ALEN);
|
||||||
|
wpa_s->links[link_id].freq = bss->mld_links[i].freq;
|
||||||
|
wpa_s->links[link_id].bss = wpa_bss_get_bssid(wpa_s, bssid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void sme_send_authentication(struct wpa_supplicant *wpa_s,
|
static void sme_send_authentication(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_bss *bss, struct wpa_ssid *ssid,
|
struct wpa_bss *bss, struct wpa_ssid *ssid,
|
||||||
int start)
|
int start)
|
||||||
|
@ -769,8 +571,14 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
|
|
||||||
os_memset(¶ms, 0, sizeof(params));
|
os_memset(¶ms, 0, sizeof(params));
|
||||||
if (wpas_ml_element(wpa_s, bss, ssid)) {
|
|
||||||
|
if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
|
||||||
|
!wpa_bss_parse_basic_ml_element(wpa_s, bss, wpa_s->ap_mld_addr,
|
||||||
|
NULL, ssid) &&
|
||||||
|
bss->n_mld_links) {
|
||||||
wpa_printf(MSG_DEBUG, "MLD: In authentication");
|
wpa_printf(MSG_DEBUG, "MLD: In authentication");
|
||||||
|
wpas_sme_set_mlo_links(wpa_s, bss);
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
bss = wpas_ml_connect_pref(wpa_s, bss);
|
bss = wpas_ml_connect_pref(wpa_s, bss);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue