mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 21:24:08 +08:00
mac80211: support non-inheritance element
Subelement profile may specify element IDs it doesn't inherit from the management frame. Support it. Signed-off-by: Sara Sharon <sara.sharon@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
f7dacfb114
commit
671042a4fb
@ -894,10 +894,10 @@ EXPORT_SYMBOL(ieee80211_queue_delayed_work);
|
|||||||
static u32
|
static u32
|
||||||
_ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
|
_ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
|
||||||
struct ieee802_11_elems *elems,
|
struct ieee802_11_elems *elems,
|
||||||
u64 filter, u32 crc, u8 *transmitter_bssid,
|
u64 filter, u32 crc,
|
||||||
u8 *bss_bssid)
|
const struct element *check_inherit)
|
||||||
{
|
{
|
||||||
const struct element *elem, *sub;
|
const struct element *elem;
|
||||||
bool calc_crc = filter != 0;
|
bool calc_crc = filter != 0;
|
||||||
DECLARE_BITMAP(seen_elems, 256);
|
DECLARE_BITMAP(seen_elems, 256);
|
||||||
const u8 *ie;
|
const u8 *ie;
|
||||||
@ -910,6 +910,11 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
|
|||||||
u8 elen = elem->datalen;
|
u8 elen = elem->datalen;
|
||||||
const u8 *pos = elem->data;
|
const u8 *pos = elem->data;
|
||||||
|
|
||||||
|
if (check_inherit &&
|
||||||
|
!cfg80211_is_element_inherited(elem,
|
||||||
|
check_inherit))
|
||||||
|
continue;
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case WLAN_EID_SSID:
|
case WLAN_EID_SSID:
|
||||||
case WLAN_EID_SUPP_RATES:
|
case WLAN_EID_SUPP_RATES:
|
||||||
@ -1208,57 +1213,6 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
|
|||||||
if (elen >= sizeof(*elems->max_idle_period_ie))
|
if (elen >= sizeof(*elems->max_idle_period_ie))
|
||||||
elems->max_idle_period_ie = (void *)pos;
|
elems->max_idle_period_ie = (void *)pos;
|
||||||
break;
|
break;
|
||||||
case WLAN_EID_MULTIPLE_BSSID:
|
|
||||||
if (!bss_bssid || !transmitter_bssid || elen < 4)
|
|
||||||
break;
|
|
||||||
|
|
||||||
elems->max_bssid_indicator = pos[0];
|
|
||||||
|
|
||||||
for_each_element(sub, pos + 1, elen - 1) {
|
|
||||||
u8 sub_len = sub->datalen;
|
|
||||||
u8 new_bssid[ETH_ALEN];
|
|
||||||
const u8 *index;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* we only expect the "non-transmitted BSSID
|
|
||||||
* profile" subelement (subelement id 0)
|
|
||||||
*/
|
|
||||||
if (sub->id != 0 || sub->datalen < 4) {
|
|
||||||
/* not a valid BSS profile */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sub->data[0] != WLAN_EID_NON_TX_BSSID_CAP ||
|
|
||||||
sub->data[1] != 2) {
|
|
||||||
/* The first element of the
|
|
||||||
* Nontransmitted BSSID Profile is not
|
|
||||||
* the Nontransmitted BSSID Capability
|
|
||||||
* element.
|
|
||||||
*/
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* found a Nontransmitted BSSID Profile */
|
|
||||||
index = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
|
|
||||||
sub->data, sub_len);
|
|
||||||
if (!index || index[1] < 1 || index[2] == 0) {
|
|
||||||
/* Invalid MBSSID Index element */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg80211_gen_new_bssid(transmitter_bssid,
|
|
||||||
pos[0],
|
|
||||||
index[2],
|
|
||||||
new_bssid);
|
|
||||||
if (ether_addr_equal(new_bssid, bss_bssid)) {
|
|
||||||
elems->nontransmitted_bssid_profile =
|
|
||||||
(void *)sub;
|
|
||||||
elems->bssid_index_len = index[1];
|
|
||||||
elems->bssid_index = (void *)&index[2];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case WLAN_EID_EXTENSION:
|
case WLAN_EID_EXTENSION:
|
||||||
if (pos[0] == WLAN_EID_EXT_HE_MU_EDCA &&
|
if (pos[0] == WLAN_EID_EXT_HE_MU_EDCA &&
|
||||||
elen >= (sizeof(*elems->mu_edca_param_set) + 1)) {
|
elen >= (sizeof(*elems->mu_edca_param_set) + 1)) {
|
||||||
@ -1300,25 +1254,91 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
|
|||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ieee802_11_find_bssid_profile(const u8 *start, size_t len,
|
||||||
|
struct ieee802_11_elems *elems,
|
||||||
|
u8 *transmitter_bssid,
|
||||||
|
u8 *bss_bssid)
|
||||||
|
{
|
||||||
|
const struct element *elem, *sub;
|
||||||
|
|
||||||
|
if (!bss_bssid || !transmitter_bssid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, start, len) {
|
||||||
|
if (elem->datalen < 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for_each_element(sub, elem->data + 1, elem->datalen - 1) {
|
||||||
|
u8 new_bssid[ETH_ALEN];
|
||||||
|
const u8 *index;
|
||||||
|
|
||||||
|
if (sub->id != 0 || sub->datalen < 4) {
|
||||||
|
/* not a valid BSS profile */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sub->data[0] != WLAN_EID_NON_TX_BSSID_CAP ||
|
||||||
|
sub->data[1] != 2) {
|
||||||
|
/* The first element of the
|
||||||
|
* Nontransmitted BSSID Profile is not
|
||||||
|
* the Nontransmitted BSSID Capability
|
||||||
|
* element.
|
||||||
|
*/
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* found a Nontransmitted BSSID Profile */
|
||||||
|
index = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
|
||||||
|
sub->data, sub->datalen);
|
||||||
|
if (!index || index[1] < 1 || index[2] == 0) {
|
||||||
|
/* Invalid MBSSID Index element */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg80211_gen_new_bssid(transmitter_bssid,
|
||||||
|
elem->data[0],
|
||||||
|
index[2],
|
||||||
|
new_bssid);
|
||||||
|
if (ether_addr_equal(new_bssid, bss_bssid)) {
|
||||||
|
elems->nontransmitted_bssid_profile =
|
||||||
|
elem->data;
|
||||||
|
elems->bssid_index_len = index[1];
|
||||||
|
elems->bssid_index = (void *)&index[2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
|
u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
|
||||||
struct ieee802_11_elems *elems,
|
struct ieee802_11_elems *elems,
|
||||||
u64 filter, u32 crc, u8 *transmitter_bssid,
|
u64 filter, u32 crc, u8 *transmitter_bssid,
|
||||||
u8 *bss_bssid)
|
u8 *bss_bssid)
|
||||||
{
|
{
|
||||||
|
const struct element *non_inherit = NULL;
|
||||||
|
|
||||||
memset(elems, 0, sizeof(*elems));
|
memset(elems, 0, sizeof(*elems));
|
||||||
elems->ie_start = start;
|
elems->ie_start = start;
|
||||||
elems->total_len = len;
|
elems->total_len = len;
|
||||||
|
|
||||||
|
ieee802_11_find_bssid_profile(start, len, elems, transmitter_bssid,
|
||||||
|
bss_bssid);
|
||||||
|
|
||||||
|
if (elems->nontransmitted_bssid_profile)
|
||||||
|
non_inherit =
|
||||||
|
cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
|
||||||
|
&elems->nontransmitted_bssid_profile[2],
|
||||||
|
elems->nontransmitted_bssid_profile[1]);
|
||||||
|
|
||||||
crc = _ieee802_11_parse_elems_crc(start, len, action, elems, filter,
|
crc = _ieee802_11_parse_elems_crc(start, len, action, elems, filter,
|
||||||
crc, transmitter_bssid, bss_bssid);
|
crc, non_inherit);
|
||||||
|
|
||||||
/* Override with nontransmitted profile, if found */
|
/* Override with nontransmitted profile, if found */
|
||||||
if (transmitter_bssid && elems->nontransmitted_bssid_profile) {
|
if (transmitter_bssid && elems->nontransmitted_bssid_profile) {
|
||||||
const u8 *profile = elems->nontransmitted_bssid_profile;
|
const u8 *profile = elems->nontransmitted_bssid_profile;
|
||||||
|
|
||||||
_ieee802_11_parse_elems_crc(&profile[2], profile[1],
|
_ieee802_11_parse_elems_crc(&profile[2], profile[1],
|
||||||
action, elems, 0, 0,
|
action, elems, 0, 0, NULL);
|
||||||
transmitter_bssid, bss_bssid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elems->tim && !elems->parse_error) {
|
if (elems->tim && !elems->parse_error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user