mac80211: support profile split between elements
authorSara Sharon <sara.sharon@intel.com>
Fri, 15 Mar 2019 15:39:06 +0000 (17:39 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 26 Apr 2019 11:02:11 +0000 (13:02 +0200)
Since an element is limited to 255 octets, a profile may be split
split to several elements. Support the split as defined in the 11ax
draft 3.

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>
net/mac80211/ieee80211_i.h
net/mac80211/util.c

index e170f986d226891542bb351d6d3ea30dde44fb7b..c5708f8a7401c1628342406a2daf6a284ef9af7d 100644 (file)
@@ -1505,7 +1505,6 @@ struct ieee802_11_elems {
        const struct ieee80211_bss_max_idle_period_ie *max_idle_period_ie;
        const struct ieee80211_multiple_bssid_configuration *mbssid_config_ie;
        const struct ieee80211_bssid_index *bssid_index;
-       const u8 *nontransmitted_bssid_profile;
        u8 max_bssid_indicator;
        u8 dtim_count;
        u8 dtim_period;
index 08197afdb7b37972580db86772c43b1a64e87475..99dd58454592a6227657dc95727a5e4283d944e2 100644 (file)
@@ -1254,15 +1254,18 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
        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)
+static size_t ieee802_11_find_bssid_profile(const u8 *start, size_t len,
+                                           struct ieee802_11_elems *elems,
+                                           u8 *transmitter_bssid,
+                                           u8 *bss_bssid,
+                                           u8 **nontransmitted_profile)
 {
        const struct element *elem, *sub;
+       size_t profile_len = 0;
+       bool found = false;
 
        if (!bss_bssid || !transmitter_bssid)
-               return;
+               return profile_len;
 
        for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, start, len) {
                if (elem->datalen < 2)
@@ -1287,9 +1290,17 @@ static void ieee802_11_find_bssid_profile(const u8 *start, size_t len,
                                continue;
                        }
 
+                       memset(*nontransmitted_profile, 0, len);
+                       profile_len = cfg80211_merge_profile(start, len,
+                                                            elem,
+                                                            sub,
+                                                            nontransmitted_profile,
+                                                            len);
+
                        /* found a Nontransmitted BSSID Profile */
                        index = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
-                                                sub->data, sub->datalen);
+                                                *nontransmitted_profile,
+                                                profile_len);
                        if (!index || index[1] < 1 || index[2] == 0) {
                                /* Invalid MBSSID Index element */
                                continue;
@@ -1300,14 +1311,15 @@ static void ieee802_11_find_bssid_profile(const u8 *start, size_t len,
                                               index[2],
                                               new_bssid);
                        if (ether_addr_equal(new_bssid, bss_bssid)) {
-                               elems->nontransmitted_bssid_profile =
-                                       elem->data;
+                               found = true;
                                elems->bssid_index_len = index[1];
                                elems->bssid_index = (void *)&index[2];
                                break;
                        }
                }
        }
+
+       return found ? profile_len : 0;
 }
 
 u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
@@ -1316,30 +1328,34 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
                               u8 *bss_bssid)
 {
        const struct element *non_inherit = NULL;
+       u8 *nontransmitted_profile;
+       int nontransmitted_profile_len = 0;
 
        memset(elems, 0, sizeof(*elems));
        elems->ie_start = start;
        elems->total_len = len;
 
-       ieee802_11_find_bssid_profile(start, len, elems, transmitter_bssid,
-                                     bss_bssid);
-
-       if (elems->nontransmitted_bssid_profile)
+       nontransmitted_profile = kmalloc(len, GFP_ATOMIC);
+       if (nontransmitted_profile) {
+               nontransmitted_profile_len =
+                       ieee802_11_find_bssid_profile(start, len, elems,
+                                                     transmitter_bssid,
+                                                     bss_bssid,
+                                                     &nontransmitted_profile);
                non_inherit =
                        cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
-                                              &elems->nontransmitted_bssid_profile[2],
-                                              elems->nontransmitted_bssid_profile[1]);
+                                              nontransmitted_profile,
+                                              nontransmitted_profile_len);
+       }
 
        crc = _ieee802_11_parse_elems_crc(start, len, action, elems, filter,
                                          crc, non_inherit);
 
        /* Override with nontransmitted profile, if found */
-       if (transmitter_bssid && elems->nontransmitted_bssid_profile) {
-               const u8 *profile = elems->nontransmitted_bssid_profile;
-
-               _ieee802_11_parse_elems_crc(&profile[2], profile[1],
+       if (nontransmitted_profile_len)
+               _ieee802_11_parse_elems_crc(nontransmitted_profile,
+                                           nontransmitted_profile_len,
                                            action, elems, 0, 0, NULL);
-       }
 
        if (elems->tim && !elems->parse_error) {
                const struct ieee80211_tim_ie *tim_ie = elems->tim;
@@ -1359,6 +1375,8 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
            offsetofend(struct ieee80211_bssid_index, dtim_count))
                elems->dtim_count = elems->bssid_index->dtim_count;
 
+       kfree(nontransmitted_profile);
+
        return crc;
 }