Skip to content

Commit c5fd399

Browse files
donnaskiezjmberg-intel
authored andcommitted
wifi: mac80211: correctly identify S1G short beacon
mac80211 identifies a short beacon by the presence of the next TBTT field, however the standard actually doesn't explicitly state that the next TBTT can't be in a long beacon or even that it is required in a short beacon - and as a result this validation does not work for all vendor implementations. The standard explicitly states that an S1G long beacon shall contain the S1G beacon compatibility element as the first element in a beacon transmitted at a TBTT that is not a TSBTT (Target Short Beacon Transmission Time) as per IEEE80211-2024 11.1.3.10.1. This is validated by 9.3.4.3 Table 9-76 which states that the S1G beacon compatibility element is only allowed in the full set and is not allowed in the minimum set of elements permitted for use within short beacons. Correctly identify short beacons by the lack of an S1G beacon compatibility element as the first element in an S1G beacon frame. Fixes: 9eaffe5 ("cfg80211: convert S1G beacon to scan results") Signed-off-by: Simon Wadsworth <[email protected]> Signed-off-by: Lachlan Hodges <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Johannes Berg <[email protected]>
1 parent 74b1ec9 commit c5fd399

File tree

2 files changed

+38
-14
lines changed

2 files changed

+38
-14
lines changed

include/linux/ieee80211.h

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -662,18 +662,6 @@ static inline bool ieee80211_s1g_has_cssid(__le16 fc)
662662
(fc & cpu_to_le16(IEEE80211_S1G_BCN_CSSID));
663663
}
664664

665-
/**
666-
* ieee80211_is_s1g_short_beacon - check if frame is an S1G short beacon
667-
* @fc: frame control bytes in little-endian byteorder
668-
* Return: whether or not the frame is an S1G short beacon,
669-
* i.e. it is an S1G beacon with 'next TBTT' flag set
670-
*/
671-
static inline bool ieee80211_is_s1g_short_beacon(__le16 fc)
672-
{
673-
return ieee80211_is_s1g_beacon(fc) &&
674-
(fc & cpu_to_le16(IEEE80211_S1G_BCN_NEXT_TBTT));
675-
}
676-
677665
/**
678666
* ieee80211_is_atim - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ATIM
679667
* @fc: frame control bytes in little-endian byteorder
@@ -4901,6 +4889,39 @@ static inline bool ieee80211_is_ftm(struct sk_buff *skb)
49014889
return false;
49024890
}
49034891

4892+
/**
4893+
* ieee80211_is_s1g_short_beacon - check if frame is an S1G short beacon
4894+
* @fc: frame control bytes in little-endian byteorder
4895+
* @variable: pointer to the beacon frame elements
4896+
* @variable_len: length of the frame elements
4897+
* Return: whether or not the frame is an S1G short beacon. As per
4898+
* IEEE80211-2024 11.1.3.10.1, The S1G beacon compatibility element shall
4899+
* always be present as the first element in beacon frames generated at a
4900+
* TBTT (Target Beacon Transmission Time), so any frame not containing
4901+
* this element must have been generated at a TSBTT (Target Short Beacon
4902+
* Transmission Time) that is not a TBTT. Additionally, short beacons are
4903+
* prohibited from containing the S1G beacon compatibility element as per
4904+
* IEEE80211-2024 9.3.4.3 Table 9-76, so if we have an S1G beacon with
4905+
* either no elements or the first element is not the beacon compatibility
4906+
* element, we have a short beacon.
4907+
*/
4908+
static inline bool ieee80211_is_s1g_short_beacon(__le16 fc, const u8 *variable,
4909+
size_t variable_len)
4910+
{
4911+
if (!ieee80211_is_s1g_beacon(fc))
4912+
return false;
4913+
4914+
/*
4915+
* If the frame does not contain at least 1 element (this is perfectly
4916+
* valid in a short beacon) and is an S1G beacon, we have a short
4917+
* beacon.
4918+
*/
4919+
if (variable_len < 2)
4920+
return true;
4921+
4922+
return variable[0] != WLAN_EID_S1G_BCN_COMPAT;
4923+
}
4924+
49044925
struct element {
49054926
u8 id;
49064927
u8 datalen;

net/mac80211/mlme.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7195,6 +7195,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
71957195
struct ieee80211_bss_conf *bss_conf = link->conf;
71967196
struct ieee80211_vif_cfg *vif_cfg = &sdata->vif.cfg;
71977197
struct ieee80211_mgmt *mgmt = (void *) hdr;
7198+
struct ieee80211_ext *ext = NULL;
71987199
size_t baselen;
71997200
struct ieee802_11_elems *elems;
72007201
struct ieee80211_local *local = sdata->local;
@@ -7220,7 +7221,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
72207221
/* Process beacon from the current BSS */
72217222
bssid = ieee80211_get_bssid(hdr, len, sdata->vif.type);
72227223
if (ieee80211_is_s1g_beacon(mgmt->frame_control)) {
7223-
struct ieee80211_ext *ext = (void *) mgmt;
7224+
ext = (void *)mgmt;
72247225
variable = ext->u.s1g_beacon.variable +
72257226
ieee80211_s1g_optional_len(ext->frame_control);
72267227
}
@@ -7407,7 +7408,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
74077408
}
74087409

74097410
if ((ncrc == link->u.mgd.beacon_crc && link->u.mgd.beacon_crc_valid) ||
7410-
ieee80211_is_s1g_short_beacon(mgmt->frame_control))
7411+
(ext && ieee80211_is_s1g_short_beacon(ext->frame_control,
7412+
parse_params.start,
7413+
parse_params.len)))
74117414
goto free;
74127415
link->u.mgd.beacon_crc = ncrc;
74137416
link->u.mgd.beacon_crc_valid = true;

0 commit comments

Comments
 (0)