mac80211: convert S1G beacon to scan results
authorThomas Pedersen <thomas@adapt-ip.com>
Tue, 22 Sep 2020 02:28:08 +0000 (19:28 -0700)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 28 Sep 2020 11:53:25 +0000 (13:53 +0200)
This commit finds the correct offset for Information
Elements in S1G beacon frames so they can be reported in
scan results.

Signed-off-by: Thomas Pedersen <thomas@adapt-ip.com>
Link: https://lore.kernel.org/r/20200922022818.15855-8-thomas@adapt-ip.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/ieee80211_i.h
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/util.c

index 3084417..f6b209e 100644 (file)
@@ -1535,6 +1535,9 @@ struct ieee802_11_elems {
        u8 dtim_count;
        u8 dtim_period;
        const struct ieee80211_addba_ext_ie *addba_ext_ie;
+       const struct ieee80211_s1g_cap *s1g_capab;
+       const struct ieee80211_s1g_oper_ie *s1g_oper;
+       const struct ieee80211_s1g_bcn_compat_ie *s1g_bcn_compat;
 
        /* length of them, respectively */
        u8 ext_capab_len;
index 7f88a1b..4fb3e42 100644 (file)
@@ -4578,7 +4578,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
        ieee80211_verify_alignment(&rx);
 
        if (unlikely(ieee80211_is_probe_resp(hdr->frame_control) ||
-                    ieee80211_is_beacon(hdr->frame_control)))
+                    ieee80211_is_beacon(hdr->frame_control) ||
+                    ieee80211_is_s1g_beacon(hdr->frame_control)))
                ieee80211_scan_rx(local, skb);
 
        if (ieee80211_is_data(fc)) {
index d211160..d4cc9ac 100644 (file)
@@ -146,7 +146,8 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
                          struct ieee80211_mgmt *mgmt, size_t len,
                          struct ieee80211_channel *channel)
 {
-       bool beacon = ieee80211_is_beacon(mgmt->frame_control);
+       bool beacon = ieee80211_is_beacon(mgmt->frame_control) ||
+                     ieee80211_is_s1g_beacon(mgmt->frame_control);
        struct cfg80211_bss *cbss, *non_tx_cbss;
        struct ieee80211_bss *bss, *non_tx_bss;
        struct cfg80211_inform_bss bss_meta = {
@@ -195,6 +196,11 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
                elements = mgmt->u.probe_resp.variable;
                baselen = offsetof(struct ieee80211_mgmt,
                                   u.probe_resp.variable);
+       } else if (ieee80211_is_s1g_beacon(mgmt->frame_control)) {
+               struct ieee80211_ext *ext = (void *) mgmt;
+
+               baselen = offsetof(struct ieee80211_ext, u.s1g_beacon.variable);
+               elements = ext->u.s1g_beacon.variable;
        } else {
                baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
                elements = mgmt->u.beacon.variable;
@@ -246,9 +252,12 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
        struct ieee80211_bss *bss;
        struct ieee80211_channel *channel;
 
-       if (skb->len < 24 ||
-           (!ieee80211_is_probe_resp(mgmt->frame_control) &&
-            !ieee80211_is_beacon(mgmt->frame_control)))
+       if (ieee80211_is_s1g_beacon(mgmt->frame_control)) {
+               if (skb->len < 15)
+                       return;
+       } else if (skb->len < 24 ||
+                (!ieee80211_is_probe_resp(mgmt->frame_control) &&
+                 !ieee80211_is_beacon(mgmt->frame_control)))
                return;
 
        sdata1 = rcu_dereference(local->scan_sdata);
index 5802275..c34cdac 100644 (file)
@@ -1003,6 +1003,10 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
                case WLAN_EID_LINK_ID:
                case WLAN_EID_BSS_MAX_IDLE_PERIOD:
                case WLAN_EID_RSNX:
+               case WLAN_EID_S1G_BCN_COMPAT:
+               case WLAN_EID_S1G_CAPABILITIES:
+               case WLAN_EID_S1G_OPERATION:
+               case WLAN_EID_S1G_SHORT_BCN_INTERVAL:
                /*
                 * not listing WLAN_EID_CHANNEL_SWITCH_WRAPPER -- it seems possible
                 * that if the content gets bigger it might be needed more than once
@@ -1288,6 +1292,24 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
                                                                &crc : NULL,
                                                          elem, elems);
                        break;
+               case WLAN_EID_S1G_CAPABILITIES:
+                       if (elen == sizeof(*elems->s1g_capab))
+                               elems->s1g_capab = (void *)pos;
+                       else
+                               elem_parse_failed = true;
+                       break;
+               case WLAN_EID_S1G_OPERATION:
+                       if (elen == sizeof(*elems->s1g_oper))
+                               elems->s1g_oper = (void *)pos;
+                       else
+                               elem_parse_failed = true;
+                       break;
+               case WLAN_EID_S1G_BCN_COMPAT:
+                       if (elen == sizeof(*elems->s1g_bcn_compat))
+                               elems->s1g_bcn_compat = (void *)pos;
+                       else
+                               elem_parse_failed = true;
+                       break;
                default:
                        break;
                }