mbssid: Process Known BSSID element
Process the Known BSSID elements if included by non-AP stations. The format is described in IEEE Std 802.11ax-2021, 9.4.2.261. Non-AP stations may include this element in directed Probe Request frames to indicate which of the multiple BSSIDs they have already discovered. AP should exclude these profiles from the Probe Response frame. Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
This commit is contained in:
parent
15690faada
commit
10749c3c48
6 changed files with 54 additions and 20 deletions
|
@ -478,7 +478,8 @@ ieee802_11_build_ap_params_mbssid(struct hostapd_data *hapd,
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
tx_bss = hostapd_mbssid_get_tx_bss(hapd);
|
tx_bss = hostapd_mbssid_get_tx_bss(hapd);
|
||||||
len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &elem_count);
|
len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &elem_count,
|
||||||
|
NULL, 0);
|
||||||
if (!len || (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
|
if (!len || (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
|
||||||
elem_count > iface->ema_max_periodicity))
|
elem_count > iface->ema_max_periodicity))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -492,7 +493,7 @@ ieee802_11_build_ap_params_mbssid(struct hostapd_data *hapd,
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
end = hostapd_eid_mbssid(tx_bss, elem, elem + len, WLAN_FC_STYPE_BEACON,
|
end = hostapd_eid_mbssid(tx_bss, elem, elem + len, WLAN_FC_STYPE_BEACON,
|
||||||
elem_count, elem_offset);
|
elem_count, elem_offset, NULL, 0);
|
||||||
|
|
||||||
params->mbssid_tx_iface = tx_bss->conf->iface;
|
params->mbssid_tx_iface = tx_bss->conf->iface;
|
||||||
params->mbssid_index = hostapd_mbssid_get_bss_index(hapd);
|
params->mbssid_index = hostapd_mbssid_get_bss_index(hapd);
|
||||||
|
@ -532,7 +533,8 @@ static u8 * hostapd_eid_mbssid_config(struct hostapd_data *hapd, u8 *eid,
|
||||||
static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
||||||
const struct ieee80211_mgmt *req,
|
const struct ieee80211_mgmt *req,
|
||||||
int is_p2p, size_t *resp_len,
|
int is_p2p, size_t *resp_len,
|
||||||
bool bcast_probe_resp)
|
bool bcast_probe_resp, const u8 *known_bss,
|
||||||
|
u8 known_bss_len)
|
||||||
{
|
{
|
||||||
struct ieee80211_mgmt *resp;
|
struct ieee80211_mgmt *resp;
|
||||||
u8 *pos, *epos, *csa_pos;
|
u8 *pos, *epos, *csa_pos;
|
||||||
|
@ -586,7 +588,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL);
|
buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL,
|
||||||
|
known_bss, known_bss_len);
|
||||||
buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
|
buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
|
||||||
buflen += hostapd_mbo_ie_len(hapd);
|
buflen += hostapd_mbo_ie_len(hapd);
|
||||||
buflen += hostapd_eid_owe_trans_len(hapd);
|
buflen += hostapd_eid_owe_trans_len(hapd);
|
||||||
|
@ -647,7 +650,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
||||||
pos = hostapd_get_rsne(hapd, pos, epos - pos);
|
pos = hostapd_get_rsne(hapd, pos, epos - pos);
|
||||||
pos = hostapd_eid_bss_load(hapd, pos, epos - pos);
|
pos = hostapd_eid_bss_load(hapd, pos, epos - pos);
|
||||||
pos = hostapd_eid_mbssid(hapd, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0,
|
pos = hostapd_eid_mbssid(hapd, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0,
|
||||||
NULL);
|
NULL, known_bss, known_bss_len);
|
||||||
pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos);
|
pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos);
|
||||||
pos = hostapd_get_mde(hapd, pos, epos - pos);
|
pos = hostapd_get_mde(hapd, pos, epos - pos);
|
||||||
|
|
||||||
|
@ -661,9 +664,11 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
||||||
pos = hostapd_eid_ht_capabilities(hapd, pos);
|
pos = hostapd_eid_ht_capabilities(hapd, pos);
|
||||||
pos = hostapd_eid_ht_operation(hapd, pos);
|
pos = hostapd_eid_ht_operation(hapd, pos);
|
||||||
|
|
||||||
/* Probe Response frames always include all non-TX profiles */
|
/* Probe Response frames always include all non-TX profiles except
|
||||||
|
* when a list of known BSSes is included in the Probe Request frame. */
|
||||||
pos = hostapd_eid_ext_capab(hapd, pos,
|
pos = hostapd_eid_ext_capab(hapd, pos,
|
||||||
hapd->iconf->mbssid >= MBSSID_ENABLED);
|
hapd->iconf->mbssid >= MBSSID_ENABLED &&
|
||||||
|
!known_bss_len);
|
||||||
|
|
||||||
pos = hostapd_eid_time_adv(hapd, pos);
|
pos = hostapd_eid_time_adv(hapd, pos);
|
||||||
pos = hostapd_eid_time_zone(hapd, pos);
|
pos = hostapd_eid_time_zone(hapd, pos);
|
||||||
|
@ -1225,7 +1230,8 @@ void handle_probe_req(struct hostapd_data *hapd,
|
||||||
" signal=%d", MAC2STR(mgmt->sa), ssi_signal);
|
" signal=%d", MAC2STR(mgmt->sa), ssi_signal);
|
||||||
|
|
||||||
resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
|
resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
|
||||||
&resp_len, false);
|
&resp_len, false, elems.mbssid_known_bss,
|
||||||
|
elems.mbssid_known_bss_len);
|
||||||
if (resp == NULL)
|
if (resp == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1295,7 +1301,7 @@ static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
|
||||||
"this");
|
"this");
|
||||||
|
|
||||||
/* Generate a Probe Response template for the non-P2P case */
|
/* Generate a Probe Response template for the non-P2P case */
|
||||||
return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false);
|
return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* NEED_AP_MLME */
|
#endif /* NEED_AP_MLME */
|
||||||
|
@ -1314,7 +1320,7 @@ static u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd,
|
||||||
|
|
||||||
return hostapd_gen_probe_resp(hapd, NULL, 0,
|
return hostapd_gen_probe_resp(hapd, NULL, 0,
|
||||||
¶ms->unsol_bcast_probe_resp_tmpl_len,
|
¶ms->unsol_bcast_probe_resp_tmpl_len,
|
||||||
true);
|
true, NULL, 0);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211AX */
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
|
||||||
|
|
|
@ -6725,8 +6725,20 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool mbssid_known_bss(unsigned int i, const u8 *known_bss,
|
||||||
|
size_t known_bss_len)
|
||||||
|
{
|
||||||
|
if (!known_bss || known_bss_len <= i / 8)
|
||||||
|
return false;
|
||||||
|
known_bss = &known_bss[i / 8];
|
||||||
|
return *known_bss & (u8) (BIT(i % 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
|
static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
|
||||||
u32 frame_type, size_t *bss_index)
|
u32 frame_type, size_t *bss_index,
|
||||||
|
const u8 *known_bss,
|
||||||
|
size_t known_bss_len)
|
||||||
{
|
{
|
||||||
struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
|
struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
|
||||||
size_t len = 3, i;
|
size_t len = 3, i;
|
||||||
|
@ -6737,7 +6749,8 @@ static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
|
||||||
size_t nontx_profile_len, auth_len;
|
size_t nontx_profile_len, auth_len;
|
||||||
u8 ie_count = 0;
|
u8 ie_count = 0;
|
||||||
|
|
||||||
if (!bss || !bss->conf || !bss->started)
|
if (!bss || !bss->conf || !bss->started ||
|
||||||
|
mbssid_known_bss(i, known_bss, known_bss_len))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -6786,7 +6799,8 @@ static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
|
||||||
|
|
||||||
|
|
||||||
size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
|
size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
|
||||||
u8 *elem_count)
|
u8 *elem_count, const u8 *known_bss,
|
||||||
|
size_t known_bss_len)
|
||||||
{
|
{
|
||||||
size_t len = 0, bss_index = 1;
|
size_t len = 0, bss_index = 1;
|
||||||
|
|
||||||
|
@ -6806,7 +6820,8 @@ size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
|
||||||
|
|
||||||
while (bss_index < hapd->iface->num_bss) {
|
while (bss_index < hapd->iface->num_bss) {
|
||||||
len += hostapd_eid_mbssid_elem_len(hapd, frame_type,
|
len += hostapd_eid_mbssid_elem_len(hapd, frame_type,
|
||||||
&bss_index);
|
&bss_index, known_bss,
|
||||||
|
known_bss_len);
|
||||||
|
|
||||||
if (frame_type == WLAN_FC_STYPE_BEACON)
|
if (frame_type == WLAN_FC_STYPE_BEACON)
|
||||||
*elem_count += 1;
|
*elem_count += 1;
|
||||||
|
@ -6817,7 +6832,8 @@ size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
|
||||||
|
|
||||||
static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end,
|
static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end,
|
||||||
u32 frame_type, u8 max_bssid_indicator,
|
u32 frame_type, u8 max_bssid_indicator,
|
||||||
size_t *bss_index, u8 elem_count)
|
size_t *bss_index, u8 elem_count,
|
||||||
|
const u8 *known_bss, size_t known_bss_len)
|
||||||
{
|
{
|
||||||
struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
|
struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
|
||||||
size_t i;
|
size_t i;
|
||||||
|
@ -6836,7 +6852,8 @@ static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end,
|
||||||
size_t auth_len = 0;
|
size_t auth_len = 0;
|
||||||
u16 capab_info;
|
u16 capab_info;
|
||||||
|
|
||||||
if (!bss || !bss->conf || !bss->started)
|
if (!bss || !bss->conf || !bss->started ||
|
||||||
|
mbssid_known_bss(i, known_bss, known_bss_len))
|
||||||
continue;
|
continue;
|
||||||
conf = bss->conf;
|
conf = bss->conf;
|
||||||
|
|
||||||
|
@ -6919,7 +6936,8 @@ static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end,
|
||||||
|
|
||||||
u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
|
u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
|
||||||
unsigned int frame_stype, u8 elem_count,
|
unsigned int frame_stype, u8 elem_count,
|
||||||
u8 **elem_offset)
|
u8 **elem_offset,
|
||||||
|
const u8 *known_bss, size_t known_bss_len)
|
||||||
{
|
{
|
||||||
size_t bss_index = 1;
|
size_t bss_index = 1;
|
||||||
u8 elem_index = 0;
|
u8 elem_index = 0;
|
||||||
|
@ -6948,7 +6966,8 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
|
||||||
}
|
}
|
||||||
eid = hostapd_eid_mbssid_elem(hapd, eid, end, frame_stype,
|
eid = hostapd_eid_mbssid_elem(hapd, eid, end, frame_stype,
|
||||||
hostapd_max_bssid_indicator(hapd),
|
hostapd_max_bssid_indicator(hapd),
|
||||||
&bss_index, elem_count);
|
&bss_index, elem_count,
|
||||||
|
known_bss, known_bss_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
return eid;
|
return eid;
|
||||||
|
|
|
@ -216,9 +216,11 @@ u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
const u8 *he_capab, size_t he_capab_len,
|
const u8 *he_capab, size_t he_capab_len,
|
||||||
const u8 *eht_capab, size_t eht_capab_len);
|
const u8 *eht_capab, size_t eht_capab_len);
|
||||||
size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
|
size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
|
||||||
u8 *elem_count);
|
u8 *elem_count, const u8 *known_bss,
|
||||||
|
size_t known_bss_len);
|
||||||
u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
|
u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
|
||||||
unsigned int frame_stype, u8 elem_count,
|
unsigned int frame_stype, u8 elem_count,
|
||||||
u8 **elem_offset);
|
u8 **elem_offset,
|
||||||
|
const u8 *known_bss, size_t known_bss_len);
|
||||||
|
|
||||||
#endif /* IEEE802_11_H */
|
#endif /* IEEE802_11_H */
|
||||||
|
|
|
@ -387,6 +387,10 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
|
||||||
show_errors))
|
show_errors))
|
||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
case WLAN_EID_EXT_KNOWN_BSSID:
|
||||||
|
elems->mbssid_known_bss = pos;
|
||||||
|
elems->mbssid_known_bss_len = elen;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (show_errors) {
|
if (show_errors) {
|
||||||
wpa_printf(MSG_MSGDUMP,
|
wpa_printf(MSG_MSGDUMP,
|
||||||
|
|
|
@ -108,6 +108,7 @@ struct ieee802_11_elems {
|
||||||
const u8 *reconf_mle;
|
const u8 *reconf_mle;
|
||||||
const u8 *tdls_mle;
|
const u8 *tdls_mle;
|
||||||
const u8 *prior_access_mle;
|
const u8 *prior_access_mle;
|
||||||
|
const u8 *mbssid_known_bss;
|
||||||
|
|
||||||
u8 ssid_len;
|
u8 ssid_len;
|
||||||
u8 supp_rates_len;
|
u8 supp_rates_len;
|
||||||
|
@ -169,6 +170,7 @@ struct ieee802_11_elems {
|
||||||
size_t reconf_mle_len;
|
size_t reconf_mle_len;
|
||||||
size_t tdls_mle_len;
|
size_t tdls_mle_len;
|
||||||
size_t prior_access_mle_len;
|
size_t prior_access_mle_len;
|
||||||
|
u8 mbssid_known_bss_len;
|
||||||
|
|
||||||
struct mb_ies_info mb_ies;
|
struct mb_ies_info mb_ies;
|
||||||
|
|
||||||
|
|
|
@ -483,6 +483,7 @@
|
||||||
#define WLAN_EID_EXT_OCV_OCI 54
|
#define WLAN_EID_EXT_OCV_OCI 54
|
||||||
#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55
|
#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55
|
||||||
#define WLAN_EID_EXT_NON_INHERITANCE 56
|
#define WLAN_EID_EXT_NON_INHERITANCE 56
|
||||||
|
#define WLAN_EID_EXT_KNOWN_BSSID 57
|
||||||
#define WLAN_EID_EXT_SHORT_SSID_LIST 58
|
#define WLAN_EID_EXT_SHORT_SSID_LIST 58
|
||||||
#define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59
|
#define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59
|
||||||
#define WLAN_EID_EXT_EDMG_CAPABILITIES 61
|
#define WLAN_EID_EXT_EDMG_CAPABILITIES 61
|
||||||
|
|
Loading…
Reference in a new issue