Skip to content

Commit 9eaffe5

Browse files
twpedersenjmberg-intel
authored andcommitted
cfg80211: convert S1G beacon to scan results
The S1G beacon is an extension frame as opposed to management frame for the regular beacon. This means we may have to occasionally cast the frame buffer to a different header type. Luckily this isn't too bad as scan results mostly only care about the IEs. Signed-off-by: Thomas Pedersen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Johannes Berg <[email protected]>
1 parent 7957c6c commit 9eaffe5

File tree

2 files changed

+80
-9
lines changed

2 files changed

+80
-9
lines changed

include/linux/ieee80211.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@
151151

152152
#define IEEE80211_ANO_NETTYPE_WILD 15
153153

154+
/* bits unique to S1G beacon */
155+
#define IEEE80211_S1G_BCN_NEXT_TBTT 0x100
156+
154157
/* control extension - for IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTL_EXT */
155158
#define IEEE80211_CTL_EXT_POLL 0x2000
156159
#define IEEE80211_CTL_EXT_SPR 0x3000
@@ -553,6 +556,28 @@ static inline bool ieee80211_is_s1g_beacon(__le16 fc)
553556
cpu_to_le16(IEEE80211_FTYPE_EXT | IEEE80211_STYPE_S1G_BEACON);
554557
}
555558

559+
/**
560+
* ieee80211_next_tbtt_present - check if IEEE80211_FTYPE_EXT &&
561+
* IEEE80211_STYPE_S1G_BEACON && IEEE80211_S1G_BCN_NEXT_TBTT
562+
* @fc: frame control bytes in little-endian byteorder
563+
*/
564+
static inline bool ieee80211_next_tbtt_present(__le16 fc)
565+
{
566+
return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) ==
567+
cpu_to_le16(IEEE80211_FTYPE_EXT | IEEE80211_STYPE_S1G_BEACON) &&
568+
fc & cpu_to_le16(IEEE80211_S1G_BCN_NEXT_TBTT);
569+
}
570+
571+
/**
572+
* ieee80211_is_s1g_short_beacon - check if next tbtt present bit is set. Only
573+
* true for S1G beacons when they're short.
574+
* @fc: frame control bytes in little-endian byteorder
575+
*/
576+
static inline bool ieee80211_is_s1g_short_beacon(__le16 fc)
577+
{
578+
return ieee80211_is_s1g_beacon(fc) && ieee80211_next_tbtt_present(fc);
579+
}
580+
556581
/**
557582
* ieee80211_is_atim - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ATIM
558583
* @fc: frame control bytes in little-endian byteorder
@@ -1034,6 +1059,13 @@ struct ieee80211_ext {
10341059
u8 change_seq;
10351060
u8 variable[0];
10361061
} __packed s1g_beacon;
1062+
struct {
1063+
u8 sa[ETH_ALEN];
1064+
__le32 timestamp;
1065+
u8 change_seq;
1066+
u8 next_tbtt[3];
1067+
u8 variable[0];
1068+
} __packed s1g_short_beacon;
10371069
} u;
10381070
} __packed __aligned(2);
10391071

net/wireless/scan.c

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2294,8 +2294,11 @@ cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
22942294
struct cfg80211_bss_ies *ies;
22952295
struct ieee80211_channel *channel;
22962296
bool signal_valid;
2297-
size_t ielen = len - offsetof(struct ieee80211_mgmt,
2298-
u.probe_resp.variable);
2297+
struct ieee80211_ext *ext = NULL;
2298+
u8 *bssid, *variable;
2299+
u16 capability, beacon_int;
2300+
size_t ielen, min_hdr_len = offsetof(struct ieee80211_mgmt,
2301+
u.probe_resp.variable);
22992302
int bss_type;
23002303

23012304
BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) !=
@@ -2313,34 +2316,70 @@ cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
23132316
(data->signal < 0 || data->signal > 100)))
23142317
return NULL;
23152318

2316-
if (WARN_ON(len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable)))
2319+
if (ieee80211_is_s1g_beacon(mgmt->frame_control)) {
2320+
ext = (void *) mgmt;
2321+
min_hdr_len = offsetof(struct ieee80211_ext, u.s1g_beacon);
2322+
if (ieee80211_is_s1g_short_beacon(mgmt->frame_control))
2323+
min_hdr_len = offsetof(struct ieee80211_ext,
2324+
u.s1g_short_beacon.variable);
2325+
}
2326+
2327+
if (WARN_ON(len < min_hdr_len))
23172328
return NULL;
23182329

2319-
channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable,
2330+
ielen = len - min_hdr_len;
2331+
variable = mgmt->u.probe_resp.variable;
2332+
if (ext) {
2333+
if (ieee80211_is_s1g_short_beacon(mgmt->frame_control))
2334+
variable = ext->u.s1g_short_beacon.variable;
2335+
else
2336+
variable = ext->u.s1g_beacon.variable;
2337+
}
2338+
2339+
channel = cfg80211_get_bss_channel(wiphy, variable,
23202340
ielen, data->chan, data->scan_width);
23212341
if (!channel)
23222342
return NULL;
23232343

2344+
if (ext) {
2345+
struct ieee80211_s1g_bcn_compat_ie *compat;
2346+
u8 *ie;
2347+
2348+
ie = (void *)cfg80211_find_ie(WLAN_EID_S1G_BCN_COMPAT,
2349+
variable, ielen);
2350+
if (!ie)
2351+
return NULL;
2352+
compat = (void *)(ie + 2);
2353+
bssid = ext->u.s1g_beacon.sa;
2354+
capability = le16_to_cpu(compat->compat_info);
2355+
beacon_int = le16_to_cpu(compat->beacon_int);
2356+
} else {
2357+
bssid = mgmt->bssid;
2358+
beacon_int = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
2359+
capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
2360+
}
2361+
23242362
ies = kzalloc(sizeof(*ies) + ielen, gfp);
23252363
if (!ies)
23262364
return NULL;
23272365
ies->len = ielen;
23282366
ies->tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
2329-
ies->from_beacon = ieee80211_is_beacon(mgmt->frame_control);
2330-
memcpy(ies->data, mgmt->u.probe_resp.variable, ielen);
2367+
ies->from_beacon = ieee80211_is_beacon(mgmt->frame_control) ||
2368+
ieee80211_is_s1g_beacon(mgmt->frame_control);
2369+
memcpy(ies->data, variable, ielen);
23312370

23322371
if (ieee80211_is_probe_resp(mgmt->frame_control))
23332372
rcu_assign_pointer(tmp.pub.proberesp_ies, ies);
23342373
else
23352374
rcu_assign_pointer(tmp.pub.beacon_ies, ies);
23362375
rcu_assign_pointer(tmp.pub.ies, ies);
23372376

2338-
memcpy(tmp.pub.bssid, mgmt->bssid, ETH_ALEN);
2377+
memcpy(tmp.pub.bssid, bssid, ETH_ALEN);
2378+
tmp.pub.beacon_interval = beacon_int;
2379+
tmp.pub.capability = capability;
23392380
tmp.pub.channel = channel;
23402381
tmp.pub.scan_width = data->scan_width;
23412382
tmp.pub.signal = data->signal;
2342-
tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
2343-
tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
23442383
tmp.ts_boottime = data->boottime_ns;
23452384
tmp.parent_tsf = data->parent_tsf;
23462385
tmp.pub.chains = data->chains;

0 commit comments

Comments
 (0)