@@ -894,10 +894,10 @@ EXPORT_SYMBOL(ieee80211_queue_delayed_work);
894894static u32
895895_ieee802_11_parse_elems_crc (const u8 * start , size_t len , bool action ,
896896 struct ieee802_11_elems * elems ,
897- u64 filter , u32 crc , u8 * transmitter_bssid ,
898- u8 * bss_bssid )
897+ u64 filter , u32 crc ,
898+ const struct element * check_inherit )
899899{
900- const struct element * elem , * sub ;
900+ const struct element * elem ;
901901 bool calc_crc = filter != 0 ;
902902 DECLARE_BITMAP (seen_elems , 256 );
903903 const u8 * ie ;
@@ -910,6 +910,11 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
910910 u8 elen = elem -> datalen ;
911911 const u8 * pos = elem -> data ;
912912
913+ if (check_inherit &&
914+ !cfg80211_is_element_inherited (elem ,
915+ check_inherit ))
916+ continue ;
917+
913918 switch (id ) {
914919 case WLAN_EID_SSID :
915920 case WLAN_EID_SUPP_RATES :
@@ -1208,57 +1213,6 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
12081213 if (elen >= sizeof (* elems -> max_idle_period_ie ))
12091214 elems -> max_idle_period_ie = (void * )pos ;
12101215 break ;
1211- case WLAN_EID_MULTIPLE_BSSID :
1212- if (!bss_bssid || !transmitter_bssid || elen < 4 )
1213- break ;
1214-
1215- elems -> max_bssid_indicator = pos [0 ];
1216-
1217- for_each_element (sub , pos + 1 , elen - 1 ) {
1218- u8 sub_len = sub -> datalen ;
1219- u8 new_bssid [ETH_ALEN ];
1220- const u8 * index ;
1221-
1222- /*
1223- * we only expect the "non-transmitted BSSID
1224- * profile" subelement (subelement id 0)
1225- */
1226- if (sub -> id != 0 || sub -> datalen < 4 ) {
1227- /* not a valid BSS profile */
1228- continue ;
1229- }
1230-
1231- if (sub -> data [0 ] != WLAN_EID_NON_TX_BSSID_CAP ||
1232- sub -> data [1 ] != 2 ) {
1233- /* The first element of the
1234- * Nontransmitted BSSID Profile is not
1235- * the Nontransmitted BSSID Capability
1236- * element.
1237- */
1238- continue ;
1239- }
1240-
1241- /* found a Nontransmitted BSSID Profile */
1242- index = cfg80211_find_ie (WLAN_EID_MULTI_BSSID_IDX ,
1243- sub -> data , sub_len );
1244- if (!index || index [1 ] < 1 || index [2 ] == 0 ) {
1245- /* Invalid MBSSID Index element */
1246- continue ;
1247- }
1248-
1249- cfg80211_gen_new_bssid (transmitter_bssid ,
1250- pos [0 ],
1251- index [2 ],
1252- new_bssid );
1253- if (ether_addr_equal (new_bssid , bss_bssid )) {
1254- elems -> nontransmitted_bssid_profile =
1255- (void * )sub ;
1256- elems -> bssid_index_len = index [1 ];
1257- elems -> bssid_index = (void * )& index [2 ];
1258- break ;
1259- }
1260- }
1261- break ;
12621216 case WLAN_EID_EXTENSION :
12631217 if (pos [0 ] == WLAN_EID_EXT_HE_MU_EDCA &&
12641218 elen >= (sizeof (* elems -> mu_edca_param_set ) + 1 )) {
@@ -1300,25 +1254,91 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
13001254 return crc ;
13011255}
13021256
1257+ static void ieee802_11_find_bssid_profile (const u8 * start , size_t len ,
1258+ struct ieee802_11_elems * elems ,
1259+ u8 * transmitter_bssid ,
1260+ u8 * bss_bssid )
1261+ {
1262+ const struct element * elem , * sub ;
1263+
1264+ if (!bss_bssid || !transmitter_bssid )
1265+ return ;
1266+
1267+ for_each_element_id (elem , WLAN_EID_MULTIPLE_BSSID , start , len ) {
1268+ if (elem -> datalen < 2 )
1269+ continue ;
1270+
1271+ for_each_element (sub , elem -> data + 1 , elem -> datalen - 1 ) {
1272+ u8 new_bssid [ETH_ALEN ];
1273+ const u8 * index ;
1274+
1275+ if (sub -> id != 0 || sub -> datalen < 4 ) {
1276+ /* not a valid BSS profile */
1277+ continue ;
1278+ }
1279+
1280+ if (sub -> data [0 ] != WLAN_EID_NON_TX_BSSID_CAP ||
1281+ sub -> data [1 ] != 2 ) {
1282+ /* The first element of the
1283+ * Nontransmitted BSSID Profile is not
1284+ * the Nontransmitted BSSID Capability
1285+ * element.
1286+ */
1287+ continue ;
1288+ }
1289+
1290+ /* found a Nontransmitted BSSID Profile */
1291+ index = cfg80211_find_ie (WLAN_EID_MULTI_BSSID_IDX ,
1292+ sub -> data , sub -> datalen );
1293+ if (!index || index [1 ] < 1 || index [2 ] == 0 ) {
1294+ /* Invalid MBSSID Index element */
1295+ continue ;
1296+ }
1297+
1298+ cfg80211_gen_new_bssid (transmitter_bssid ,
1299+ elem -> data [0 ],
1300+ index [2 ],
1301+ new_bssid );
1302+ if (ether_addr_equal (new_bssid , bss_bssid )) {
1303+ elems -> nontransmitted_bssid_profile =
1304+ elem -> data ;
1305+ elems -> bssid_index_len = index [1 ];
1306+ elems -> bssid_index = (void * )& index [2 ];
1307+ break ;
1308+ }
1309+ }
1310+ }
1311+ }
1312+
13031313u32 ieee802_11_parse_elems_crc (const u8 * start , size_t len , bool action ,
13041314 struct ieee802_11_elems * elems ,
13051315 u64 filter , u32 crc , u8 * transmitter_bssid ,
13061316 u8 * bss_bssid )
13071317{
1318+ const struct element * non_inherit = NULL ;
1319+
13081320 memset (elems , 0 , sizeof (* elems ));
13091321 elems -> ie_start = start ;
13101322 elems -> total_len = len ;
13111323
1324+ ieee802_11_find_bssid_profile (start , len , elems , transmitter_bssid ,
1325+ bss_bssid );
1326+
1327+ if (elems -> nontransmitted_bssid_profile )
1328+ non_inherit =
1329+ cfg80211_find_ext_elem (WLAN_EID_EXT_NON_INHERITANCE ,
1330+ & elems -> nontransmitted_bssid_profile [2 ],
1331+ elems -> nontransmitted_bssid_profile [1 ]);
1332+
13121333 crc = _ieee802_11_parse_elems_crc (start , len , action , elems , filter ,
1313- crc , transmitter_bssid , bss_bssid );
1334+ crc , non_inherit );
13141335
13151336 /* Override with nontransmitted profile, if found */
13161337 if (transmitter_bssid && elems -> nontransmitted_bssid_profile ) {
13171338 const u8 * profile = elems -> nontransmitted_bssid_profile ;
13181339
13191340 _ieee802_11_parse_elems_crc (& profile [2 ], profile [1 ],
1320- action , elems , 0 , 0 ,
1321- transmitter_bssid , bss_bssid );
1341+ action , elems , 0 , 0 , NULL );
13221342 }
13231343
13241344 if (elems -> tim && !elems -> parse_error ) {
0 commit comments