wifi: cfg80211: use structs for TBTT information access
authorBenjamin Berg <benjamin.berg@intel.com>
Sun, 18 Jun 2023 18:49:52 +0000 (21:49 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 19 Jun 2023 10:05:30 +0000 (12:05 +0200)
Make the data access a bit nicer overall by using structs. There is a
small change here to also accept a TBTT information length of eight
bytes as we do not require the 20 MHz PSD information.

This also fixes a bug reading the short SSID on big endian machines.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230618214436.4c3f8901c1bc.Ic3e94fd6e1bccff7948a252ad3bb87e322690a17@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/linux/ieee80211.h
net/wireless/scan.c

index 5a27c232afdb430938cfc0689834b20348260b2a..e145af7448a31e2fa2ddcd8e54b09420164f14e5 100644 (file)
@@ -4483,9 +4483,6 @@ static inline bool for_each_element_completed(const struct element *element,
 #define IEEE80211_AP_INFO_TBTT_HDR_COUNT                       0xF0
 #define IEEE80211_TBTT_INFO_TYPE_TBTT                          0
 #define IEEE80211_TBTT_INFO_TYPE_MLD                           1
-#define IEEE80211_TBTT_INFO_OFFSET_BSSID_BSS_PARAM             9
-#define IEEE80211_TBTT_INFO_OFFSET_BSSID_SSSID_BSS_PARAM       13
-#define IEEE80211_TBTT_INFO_OFFSET_BSSID_SSSID_BSS_PARAM_MLD_PARAM     16
 
 #define IEEE80211_RNR_TBTT_PARAMS_OCT_RECOMMENDED              0x01
 #define IEEE80211_RNR_TBTT_PARAMS_SAME_SSID                    0x02
index 974a6a8240dd52410448f7b0eb35cc818e1194be..f0b4d7671d17634b875c484a401d4979966642af 100644 (file)
@@ -574,39 +574,41 @@ static void cfg80211_free_coloc_ap_list(struct list_head *coloc_ap_list)
 static int cfg80211_parse_ap_info(struct cfg80211_colocated_ap *entry,
                                  const u8 *pos, u8 length,
                                  const struct element *ssid_elem,
-                                 int s_ssid_tmp)
+                                 u32 s_ssid_tmp)
 {
-       /* skip the TBTT offset */
-       pos++;
+       u8 bss_params;
 
-       /* ignore entries with invalid BSSID */
-       if (!is_valid_ether_addr(pos))
-               return -EINVAL;
-
-       memcpy(entry->bssid, pos, ETH_ALEN);
-       pos += ETH_ALEN;
+       /* The length is already verified by the caller to contain bss_params */
+       if (length > sizeof(struct ieee80211_tbtt_info_7_8_9)) {
+               struct ieee80211_tbtt_info_ge_11 *tbtt_info = (void *)pos;
 
-       if (length >= IEEE80211_TBTT_INFO_OFFSET_BSSID_SSSID_BSS_PARAM) {
-               memcpy(&entry->short_ssid, pos,
-                      sizeof(entry->short_ssid));
+               memcpy(entry->bssid, tbtt_info->bssid, ETH_ALEN);
+               entry->short_ssid = le32_to_cpu(tbtt_info->short_ssid);
                entry->short_ssid_valid = true;
-               pos += 4;
+
+               bss_params = tbtt_info->bss_params;
+       } else {
+               struct ieee80211_tbtt_info_7_8_9 *tbtt_info = (void *)pos;
+
+               memcpy(entry->bssid, tbtt_info->bssid, ETH_ALEN);
+
+               bss_params = tbtt_info->bss_params;
        }
 
+       /* ignore entries with invalid BSSID */
+       if (!is_valid_ether_addr(entry->bssid))
+               return -EINVAL;
+
        /* skip non colocated APs */
-       if (!cfg80211_parse_bss_param(*pos, entry))
+       if (!cfg80211_parse_bss_param(bss_params, entry))
                return -EINVAL;
-       pos++;
 
-       if (length == IEEE80211_TBTT_INFO_OFFSET_BSSID_BSS_PARAM) {
-               /*
-                * no information about the short ssid. Consider the entry valid
-                * for now. It would later be dropped in case there are explicit
-                * SSIDs that need to be matched
-                */
-               if (!entry->same_ssid)
-                       return 0;
-       }
+       /* no information about the short ssid. Consider the entry valid
+        * for now. It would later be dropped in case there are explicit
+        * SSIDs that need to be matched
+        */
+       if (!entry->same_ssid && !entry->short_ssid_valid)
+               return 0;
 
        if (entry->same_ssid) {
                entry->short_ssid = s_ssid_tmp;
@@ -617,10 +619,10 @@ static int cfg80211_parse_ap_info(struct cfg80211_colocated_ap *entry,
                 * cfg80211_parse_colocated_ap(), before calling this
                 * function.
                 */
-               memcpy(&entry->ssid, &ssid_elem->data,
-                      ssid_elem->datalen);
+               memcpy(&entry->ssid, &ssid_elem->data, ssid_elem->datalen);
                entry->ssid_len = ssid_elem->datalen;
        }
+
        return 0;
 }
 
@@ -682,8 +684,11 @@ static int cfg80211_parse_colocated_ap(const struct cfg80211_bss_ies *ies,
                 * next AP info
                 */
                if (band != NL80211_BAND_6GHZ ||
-                   (length != IEEE80211_TBTT_INFO_OFFSET_BSSID_BSS_PARAM &&
-                    length < IEEE80211_TBTT_INFO_OFFSET_BSSID_SSSID_BSS_PARAM)) {
+                   !(length == offsetofend(struct ieee80211_tbtt_info_7_8_9,
+                                           bss_params) ||
+                     length == sizeof(struct ieee80211_tbtt_info_7_8_9) ||
+                     length >= offsetofend(struct ieee80211_tbtt_info_ge_11,
+                                           bss_params))) {
                        pos += count * length;
                        continue;
                }