1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright 2002-2005, Instant802 Networks, Inc.
4 * Copyright 2005-2006, Devicescape Software, Inc.
5 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
6 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
7 * Copyright 2013-2014 Intel Mobile Communications GmbH
8 * Copyright (C) 2015-2017 Intel Deutschland GmbH
9 * Copyright (C) 2018-2024 Intel Corporation
11 * element parsing for mac80211
14 #include <net/mac80211.h>
15 #include <linux/netdevice.h>
16 #include <linux/export.h>
17 #include <linux/types.h>
18 #include <linux/slab.h>
19 #include <linux/skbuff.h>
20 #include <linux/etherdevice.h>
21 #include <linux/if_arp.h>
22 #include <linux/bitmap.h>
23 #include <linux/crc32.h>
24 #include <net/net_namespace.h>
25 #include <net/cfg80211.h>
26 #include <net/rtnetlink.h>
27 #include <kunit/visibility.h>
29 #include "ieee80211_i.h"
30 #include "driver-ops.h"
37 struct ieee80211_elems_parse
{
38 /* must be first for kfree to work */
39 struct ieee802_11_elems elems
;
41 /* The basic Multi-Link element in the original elements */
42 const struct element
*ml_basic_elem
;
44 /* The reconfiguration Multi-Link element in the original elements */
45 const struct element
*ml_reconf_elem
;
48 * scratch buffer that can be used for various element parsing related
49 * tasks, e.g., element de-fragmentation etc.
53 u8 scratch
[] __counted_by(scratch_len
);
57 ieee80211_parse_extension_element(u32
*crc
,
58 const struct element
*elem
,
59 struct ieee80211_elems_parse
*elems_parse
,
60 struct ieee80211_elems_parse_params
*params
)
62 struct ieee802_11_elems
*elems
= &elems_parse
->elems
;
63 const void *data
= elem
->data
+ 1;
64 bool calc_crc
= false;
70 len
= elem
->datalen
- 1;
72 switch (elem
->data
[0]) {
73 case WLAN_EID_EXT_HE_MU_EDCA
:
74 if (params
->mode
< IEEE80211_CONN_MODE_HE
)
77 if (len
>= sizeof(*elems
->mu_edca_param_set
))
78 elems
->mu_edca_param_set
= data
;
80 case WLAN_EID_EXT_HE_CAPABILITY
:
81 if (params
->mode
< IEEE80211_CONN_MODE_HE
)
83 if (ieee80211_he_capa_size_ok(data
, len
)) {
85 elems
->he_cap_len
= len
;
88 case WLAN_EID_EXT_HE_OPERATION
:
89 if (params
->mode
< IEEE80211_CONN_MODE_HE
)
92 if (len
>= sizeof(*elems
->he_operation
) &&
93 len
>= ieee80211_he_oper_size(data
) - 1)
94 elems
->he_operation
= data
;
96 case WLAN_EID_EXT_UORA
:
97 if (params
->mode
< IEEE80211_CONN_MODE_HE
)
100 elems
->uora_element
= data
;
102 case WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME
:
104 elems
->max_channel_switch_time
= data
;
106 case WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION
:
107 if (len
>= sizeof(*elems
->mbssid_config_ie
))
108 elems
->mbssid_config_ie
= data
;
110 case WLAN_EID_EXT_HE_SPR
:
111 if (params
->mode
< IEEE80211_CONN_MODE_HE
)
113 if (len
>= sizeof(*elems
->he_spr
) &&
114 len
>= ieee80211_he_spr_size(data
) - 1)
115 elems
->he_spr
= data
;
117 case WLAN_EID_EXT_HE_6GHZ_CAPA
:
118 if (params
->mode
< IEEE80211_CONN_MODE_HE
)
120 if (len
>= sizeof(*elems
->he_6ghz_capa
))
121 elems
->he_6ghz_capa
= data
;
123 case WLAN_EID_EXT_EHT_CAPABILITY
:
124 if (params
->mode
< IEEE80211_CONN_MODE_EHT
)
126 if (ieee80211_eht_capa_size_ok(elems
->he_cap
,
129 elems
->eht_cap
= data
;
130 elems
->eht_cap_len
= len
;
133 case WLAN_EID_EXT_EHT_OPERATION
:
134 if (params
->mode
< IEEE80211_CONN_MODE_EHT
)
136 if (ieee80211_eht_oper_size_ok(data
, len
))
137 elems
->eht_operation
= data
;
140 case WLAN_EID_EXT_EHT_MULTI_LINK
:
141 if (params
->mode
< IEEE80211_CONN_MODE_EHT
)
145 if (ieee80211_mle_size_ok(data
, len
)) {
146 const struct ieee80211_multi_link_elem
*mle
=
149 switch (le16_get_bits(mle
->control
,
150 IEEE80211_ML_CONTROL_TYPE
)) {
151 case IEEE80211_ML_CONTROL_TYPE_BASIC
:
152 if (elems_parse
->ml_basic_elem
) {
153 elems
->parse_error
|=
154 IEEE80211_PARSE_ERR_DUP_NEST_ML_BASIC
;
157 elems_parse
->ml_basic_elem
= elem
;
159 case IEEE80211_ML_CONTROL_TYPE_RECONF
:
160 elems_parse
->ml_reconf_elem
= elem
;
167 case WLAN_EID_EXT_BANDWIDTH_INDICATION
:
168 if (params
->mode
< IEEE80211_CONN_MODE_EHT
)
170 if (ieee80211_bandwidth_indication_size_ok(data
, len
))
171 elems
->bandwidth_indication
= data
;
174 case WLAN_EID_EXT_TID_TO_LINK_MAPPING
:
175 if (params
->mode
< IEEE80211_CONN_MODE_EHT
)
178 if (ieee80211_tid_to_link_map_size_ok(data
, len
) &&
179 elems
->ttlm_num
< ARRAY_SIZE(elems
->ttlm
)) {
180 elems
->ttlm
[elems
->ttlm_num
] = (void *)data
;
187 *crc
= crc32_be(*crc
, (void *)elem
, elem
->datalen
+ 2);
190 static void ieee80211_parse_tpe(struct ieee80211_parsed_tpe
*tpe
,
191 const u8
*data
, u8 len
)
193 const struct ieee80211_tx_pwr_env
*env
= (const void *)data
;
194 u8 count
, interpret
, category
;
195 u8
*out
, N
, *cnt_out
= NULL
, *N_out
= NULL
;
197 if (!ieee80211_valid_tpe_element(data
, len
))
200 count
= u8_get_bits(env
->info
, IEEE80211_TX_PWR_ENV_INFO_COUNT
);
201 interpret
= u8_get_bits(env
->info
, IEEE80211_TX_PWR_ENV_INFO_INTERPRET
);
202 category
= u8_get_bits(env
->info
, IEEE80211_TX_PWR_ENV_INFO_CATEGORY
);
205 case IEEE80211_TPE_LOCAL_EIRP
:
206 out
= tpe
->max_local
[category
].power
;
207 cnt_out
= &tpe
->max_local
[category
].count
;
208 tpe
->max_local
[category
].valid
= true;
210 case IEEE80211_TPE_REG_CLIENT_EIRP
:
211 out
= tpe
->max_reg_client
[category
].power
;
212 cnt_out
= &tpe
->max_reg_client
[category
].count
;
213 tpe
->max_reg_client
[category
].valid
= true;
215 case IEEE80211_TPE_LOCAL_EIRP_PSD
:
216 out
= tpe
->psd_local
[category
].power
;
217 cnt_out
= &tpe
->psd_local
[category
].count
;
218 N_out
= &tpe
->psd_local
[category
].n
;
219 tpe
->psd_local
[category
].valid
= true;
221 case IEEE80211_TPE_REG_CLIENT_EIRP_PSD
:
222 out
= tpe
->psd_reg_client
[category
].power
;
223 cnt_out
= &tpe
->psd_reg_client
[category
].count
;
224 N_out
= &tpe
->psd_reg_client
[category
].n
;
225 tpe
->psd_reg_client
[category
].valid
= true;
230 case IEEE80211_TPE_LOCAL_EIRP
:
231 case IEEE80211_TPE_REG_CLIENT_EIRP
:
232 /* count was validated <= 3, plus 320 MHz */
233 BUILD_BUG_ON(IEEE80211_TPE_EIRP_ENTRIES_320MHZ
< 5);
234 memcpy(out
, env
->variable
, count
+ 1);
235 *cnt_out
= count
+ 1;
236 /* separately take 320 MHz if present */
237 if (count
== 3 && len
> sizeof(*env
) + count
+ 1) {
238 out
[4] = env
->variable
[4];
242 case IEEE80211_TPE_LOCAL_EIRP_PSD
:
243 case IEEE80211_TPE_REG_CLIENT_EIRP_PSD
:
245 memset(out
, env
->variable
[0],
246 IEEE80211_TPE_PSD_ENTRIES_320MHZ
);
247 *cnt_out
= IEEE80211_TPE_PSD_ENTRIES_320MHZ
;
251 N
= 1 << (count
- 1);
252 memcpy(out
, env
->variable
, N
);
256 if (len
> sizeof(*env
) + N
) {
257 int K
= u8_get_bits(env
->variable
[N
],
258 IEEE80211_TX_PWR_ENV_EXT_COUNT
);
260 K
= min(K
, IEEE80211_TPE_PSD_ENTRIES_320MHZ
- N
);
261 memcpy(out
+ N
, env
->variable
+ N
+ 1, K
);
269 _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params
*params
,
270 struct ieee80211_elems_parse
*elems_parse
,
271 const struct element
*check_inherit
)
273 struct ieee802_11_elems
*elems
= &elems_parse
->elems
;
274 const struct element
*elem
;
275 bool calc_crc
= params
->filter
!= 0;
276 DECLARE_BITMAP(seen_elems
, 256);
277 u32 crc
= params
->crc
;
279 bitmap_zero(seen_elems
, 256);
281 for_each_element(elem
, params
->start
, params
->len
) {
282 const struct element
*subelem
;
283 u8 elem_parse_failed
;
285 u8 elen
= elem
->datalen
;
286 const u8
*pos
= elem
->data
;
289 !cfg80211_is_element_inherited(elem
,
295 case WLAN_EID_SUPP_RATES
:
296 case WLAN_EID_FH_PARAMS
:
297 case WLAN_EID_DS_PARAMS
:
298 case WLAN_EID_CF_PARAMS
:
300 case WLAN_EID_IBSS_PARAMS
:
301 case WLAN_EID_CHALLENGE
:
303 case WLAN_EID_ERP_INFO
:
304 case WLAN_EID_EXT_SUPP_RATES
:
305 case WLAN_EID_HT_CAPABILITY
:
306 case WLAN_EID_HT_OPERATION
:
307 case WLAN_EID_VHT_CAPABILITY
:
308 case WLAN_EID_VHT_OPERATION
:
309 case WLAN_EID_MESH_ID
:
310 case WLAN_EID_MESH_CONFIG
:
311 case WLAN_EID_PEER_MGMT
:
316 case WLAN_EID_CHANNEL_SWITCH
:
317 case WLAN_EID_EXT_CHANSWITCH_ANN
:
318 case WLAN_EID_COUNTRY
:
319 case WLAN_EID_PWR_CONSTRAINT
:
320 case WLAN_EID_TIMEOUT_INTERVAL
:
321 case WLAN_EID_SECONDARY_CHANNEL_OFFSET
:
322 case WLAN_EID_WIDE_BW_CHANNEL_SWITCH
:
323 case WLAN_EID_CHAN_SWITCH_PARAM
:
324 case WLAN_EID_EXT_CAPABILITY
:
325 case WLAN_EID_CHAN_SWITCH_TIMING
:
326 case WLAN_EID_LINK_ID
:
327 case WLAN_EID_BSS_MAX_IDLE_PERIOD
:
329 case WLAN_EID_S1G_BCN_COMPAT
:
330 case WLAN_EID_S1G_CAPABILITIES
:
331 case WLAN_EID_S1G_OPERATION
:
332 case WLAN_EID_AID_RESPONSE
:
333 case WLAN_EID_S1G_SHORT_BCN_INTERVAL
:
335 * not listing WLAN_EID_CHANNEL_SWITCH_WRAPPER -- it seems possible
336 * that if the content gets bigger it might be needed more than once
338 if (test_bit(id
, seen_elems
)) {
339 elems
->parse_error
|=
340 IEEE80211_PARSE_ERR_DUP_ELEM
;
346 if (calc_crc
&& id
< 64 && (params
->filter
& (1ULL << id
)))
347 crc
= crc32_be(crc
, pos
- 2, elen
+ 2);
349 elem_parse_failed
= 0;
352 case WLAN_EID_LINK_ID
:
353 if (elen
+ 2 < sizeof(struct ieee80211_tdls_lnkie
)) {
355 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
358 elems
->lnk_id
= (void *)(pos
- 2);
360 case WLAN_EID_CHAN_SWITCH_TIMING
:
361 if (elen
< sizeof(struct ieee80211_ch_switch_timing
)) {
363 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
366 elems
->ch_sw_timing
= (void *)pos
;
368 case WLAN_EID_EXT_CAPABILITY
:
369 elems
->ext_capab
= pos
;
370 elems
->ext_capab_len
= elen
;
374 elems
->ssid_len
= elen
;
376 case WLAN_EID_SUPP_RATES
:
377 elems
->supp_rates
= pos
;
378 elems
->supp_rates_len
= elen
;
380 case WLAN_EID_DS_PARAMS
:
382 elems
->ds_params
= pos
;
385 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
388 if (elen
>= sizeof(struct ieee80211_tim_ie
)) {
389 elems
->tim
= (void *)pos
;
390 elems
->tim_len
= elen
;
393 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
395 case WLAN_EID_VENDOR_SPECIFIC
:
396 if (elen
>= 4 && pos
[0] == 0x00 && pos
[1] == 0x50 &&
398 /* Microsoft OUI (00:50:F2) */
401 crc
= crc32_be(crc
, pos
- 2, elen
+ 2);
403 if (elen
>= 5 && pos
[3] == 2) {
404 /* OUI Type 2 - WMM IE */
406 elems
->wmm_info
= pos
;
407 elems
->wmm_info_len
= elen
;
408 } else if (pos
[4] == 1) {
409 elems
->wmm_param
= pos
;
410 elems
->wmm_param_len
= elen
;
417 elems
->rsn_len
= elen
;
419 case WLAN_EID_ERP_INFO
:
421 elems
->erp_info
= pos
;
424 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
426 case WLAN_EID_EXT_SUPP_RATES
:
427 elems
->ext_supp_rates
= pos
;
428 elems
->ext_supp_rates_len
= elen
;
430 case WLAN_EID_HT_CAPABILITY
:
431 if (params
->mode
< IEEE80211_CONN_MODE_HT
)
433 if (elen
>= sizeof(struct ieee80211_ht_cap
))
434 elems
->ht_cap_elem
= (void *)pos
;
437 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
439 case WLAN_EID_HT_OPERATION
:
440 if (params
->mode
< IEEE80211_CONN_MODE_HT
)
442 if (elen
>= sizeof(struct ieee80211_ht_operation
))
443 elems
->ht_operation
= (void *)pos
;
446 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
448 case WLAN_EID_VHT_CAPABILITY
:
449 if (params
->mode
< IEEE80211_CONN_MODE_VHT
)
451 if (elen
>= sizeof(struct ieee80211_vht_cap
))
452 elems
->vht_cap_elem
= (void *)pos
;
455 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
457 case WLAN_EID_VHT_OPERATION
:
458 if (params
->mode
< IEEE80211_CONN_MODE_VHT
)
460 if (elen
>= sizeof(struct ieee80211_vht_operation
)) {
461 elems
->vht_operation
= (void *)pos
;
463 crc
= crc32_be(crc
, pos
- 2, elen
+ 2);
467 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
469 case WLAN_EID_OPMODE_NOTIF
:
470 if (params
->mode
< IEEE80211_CONN_MODE_VHT
)
473 elems
->opmode_notif
= pos
;
475 crc
= crc32_be(crc
, pos
- 2, elen
+ 2);
479 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
481 case WLAN_EID_MESH_ID
:
482 elems
->mesh_id
= pos
;
483 elems
->mesh_id_len
= elen
;
485 case WLAN_EID_MESH_CONFIG
:
486 if (elen
>= sizeof(struct ieee80211_meshconf_ie
))
487 elems
->mesh_config
= (void *)pos
;
490 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
492 case WLAN_EID_PEER_MGMT
:
493 elems
->peering
= pos
;
494 elems
->peering_len
= elen
;
496 case WLAN_EID_MESH_AWAKE_WINDOW
:
498 elems
->awake_window
= (void *)pos
;
502 elems
->preq_len
= elen
;
506 elems
->prep_len
= elen
;
510 elems
->perr_len
= elen
;
513 if (elen
>= sizeof(struct ieee80211_rann_ie
))
514 elems
->rann
= (void *)pos
;
517 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
519 case WLAN_EID_CHANNEL_SWITCH
:
520 if (elen
!= sizeof(struct ieee80211_channel_sw_ie
)) {
522 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
525 elems
->ch_switch_ie
= (void *)pos
;
527 case WLAN_EID_EXT_CHANSWITCH_ANN
:
528 if (elen
!= sizeof(struct ieee80211_ext_chansw_ie
)) {
530 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
533 elems
->ext_chansw_ie
= (void *)pos
;
535 case WLAN_EID_SECONDARY_CHANNEL_OFFSET
:
536 if (params
->mode
< IEEE80211_CONN_MODE_HT
)
538 if (elen
!= sizeof(struct ieee80211_sec_chan_offs_ie
)) {
540 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
543 elems
->sec_chan_offs
= (void *)pos
;
545 case WLAN_EID_CHAN_SWITCH_PARAM
:
547 sizeof(*elems
->mesh_chansw_params_ie
)) {
549 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
552 elems
->mesh_chansw_params_ie
= (void *)pos
;
554 case WLAN_EID_WIDE_BW_CHANNEL_SWITCH
:
555 if (params
->mode
< IEEE80211_CONN_MODE_VHT
)
558 if (!params
->action
) {
560 IEEE80211_PARSE_ERR_UNEXPECTED_ELEM
;
564 if (elen
< sizeof(*elems
->wide_bw_chansw_ie
)) {
566 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
569 elems
->wide_bw_chansw_ie
= (void *)pos
;
571 case WLAN_EID_CHANNEL_SWITCH_WRAPPER
:
572 if (params
->mode
< IEEE80211_CONN_MODE_VHT
)
574 if (params
->action
) {
576 IEEE80211_PARSE_ERR_UNEXPECTED_ELEM
;
580 * This is a bit tricky, but as we only care about
581 * a few elements, parse them out manually.
583 subelem
= cfg80211_find_elem(WLAN_EID_WIDE_BW_CHANNEL_SWITCH
,
586 if (subelem
->datalen
>= sizeof(*elems
->wide_bw_chansw_ie
))
587 elems
->wide_bw_chansw_ie
=
588 (void *)subelem
->data
;
591 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
594 if (params
->mode
< IEEE80211_CONN_MODE_EHT
)
597 subelem
= cfg80211_find_ext_elem(WLAN_EID_EXT_BANDWIDTH_INDICATION
,
600 const void *edata
= subelem
->data
+ 1;
601 u8 edatalen
= subelem
->datalen
- 1;
603 if (ieee80211_bandwidth_indication_size_ok(edata
,
605 elems
->bandwidth_indication
= edata
;
608 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
611 subelem
= cfg80211_find_ext_elem(WLAN_EID_TX_POWER_ENVELOPE
,
614 ieee80211_parse_tpe(&elems
->csa_tpe
,
616 subelem
->datalen
- 1);
618 case WLAN_EID_COUNTRY
:
619 elems
->country_elem
= pos
;
620 elems
->country_elem_len
= elen
;
622 case WLAN_EID_PWR_CONSTRAINT
:
625 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
628 elems
->pwr_constr_elem
= pos
;
630 case WLAN_EID_CISCO_VENDOR_SPECIFIC
:
631 /* Lots of different options exist, but we only care
632 * about the Dynamic Transmit Power Control element.
633 * First check for the Cisco OUI, then for the DTPC
638 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
642 if (pos
[0] != 0x00 || pos
[1] != 0x40 ||
643 pos
[2] != 0x96 || pos
[3] != 0x00)
648 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
653 crc
= crc32_be(crc
, pos
- 2, elen
+ 2);
655 elems
->cisco_dtpc_elem
= pos
;
657 case WLAN_EID_ADDBA_EXT
:
658 if (elen
< sizeof(struct ieee80211_addba_ext_ie
)) {
660 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
663 elems
->addba_ext_ie
= (void *)pos
;
665 case WLAN_EID_TIMEOUT_INTERVAL
:
666 if (elen
>= sizeof(struct ieee80211_timeout_interval_ie
))
667 elems
->timeout_int
= (void *)pos
;
670 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
672 case WLAN_EID_BSS_MAX_IDLE_PERIOD
:
673 if (elen
>= sizeof(*elems
->max_idle_period_ie
))
674 elems
->max_idle_period_ie
= (void *)pos
;
678 elems
->rsnx_len
= elen
;
680 case WLAN_EID_TX_POWER_ENVELOPE
:
681 if (params
->mode
< IEEE80211_CONN_MODE_HE
)
683 ieee80211_parse_tpe(&elems
->tpe
, pos
, elen
);
685 case WLAN_EID_EXTENSION
:
686 ieee80211_parse_extension_element(calc_crc
?
691 case WLAN_EID_S1G_CAPABILITIES
:
692 if (params
->mode
!= IEEE80211_CONN_MODE_S1G
)
694 if (elen
>= sizeof(*elems
->s1g_capab
))
695 elems
->s1g_capab
= (void *)pos
;
698 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
700 case WLAN_EID_S1G_OPERATION
:
701 if (params
->mode
!= IEEE80211_CONN_MODE_S1G
)
703 if (elen
== sizeof(*elems
->s1g_oper
))
704 elems
->s1g_oper
= (void *)pos
;
707 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
709 case WLAN_EID_S1G_BCN_COMPAT
:
710 if (params
->mode
!= IEEE80211_CONN_MODE_S1G
)
712 if (elen
== sizeof(*elems
->s1g_bcn_compat
))
713 elems
->s1g_bcn_compat
= (void *)pos
;
716 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
718 case WLAN_EID_AID_RESPONSE
:
719 if (params
->mode
!= IEEE80211_CONN_MODE_S1G
)
721 if (elen
== sizeof(struct ieee80211_aid_response_ie
))
722 elems
->aid_resp
= (void *)pos
;
725 IEEE80211_PARSE_ERR_BAD_ELEM_SIZE
;
731 if (elem_parse_failed
)
732 elems
->parse_error
|= elem_parse_failed
;
734 __set_bit(id
, seen_elems
);
737 if (!for_each_element_completed(elem
, params
->start
, params
->len
))
738 elems
->parse_error
|= IEEE80211_PARSE_ERR_INVALID_END
;
743 static size_t ieee802_11_find_bssid_profile(const u8
*start
, size_t len
,
744 struct ieee802_11_elems
*elems
,
745 struct cfg80211_bss
*bss
,
746 u8
*nontransmitted_profile
)
748 const struct element
*elem
, *sub
;
749 size_t profile_len
= 0;
752 if (!bss
|| !bss
->transmitted_bss
)
755 for_each_element_id(elem
, WLAN_EID_MULTIPLE_BSSID
, start
, len
) {
756 if (elem
->datalen
< 2)
758 if (elem
->data
[0] < 1 || elem
->data
[0] > 8)
761 for_each_element(sub
, elem
->data
+ 1, elem
->datalen
- 1) {
762 u8 new_bssid
[ETH_ALEN
];
765 if (sub
->id
!= 0 || sub
->datalen
< 4) {
766 /* not a valid BSS profile */
770 if (sub
->data
[0] != WLAN_EID_NON_TX_BSSID_CAP
||
772 /* The first element of the
773 * Nontransmitted BSSID Profile is not
774 * the Nontransmitted BSSID Capability
780 memset(nontransmitted_profile
, 0, len
);
781 profile_len
= cfg80211_merge_profile(start
, len
,
784 nontransmitted_profile
,
787 /* found a Nontransmitted BSSID Profile */
788 index
= cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX
,
789 nontransmitted_profile
,
791 if (!index
|| index
[1] < 1 || index
[2] == 0) {
792 /* Invalid MBSSID Index element */
796 cfg80211_gen_new_bssid(bss
->transmitted_bss
->bssid
,
800 if (ether_addr_equal(new_bssid
, bss
->bssid
)) {
802 elems
->bssid_index_len
= index
[1];
803 elems
->bssid_index
= (void *)&index
[2];
809 return found
? profile_len
: 0;
813 ieee80211_mle_get_sta_prof(struct ieee80211_elems_parse
*elems_parse
,
816 struct ieee802_11_elems
*elems
= &elems_parse
->elems
;
817 const struct ieee80211_multi_link_elem
*ml
= elems
->ml_basic
;
818 ssize_t ml_len
= elems
->ml_basic_len
;
819 const struct element
*sub
;
821 for_each_mle_subelement(sub
, (u8
*)ml
, ml_len
) {
822 struct ieee80211_mle_per_sta_profile
*prof
= (void *)sub
->data
;
823 ssize_t sta_prof_len
;
826 if (sub
->id
!= IEEE80211_MLE_SUBELEM_PER_STA_PROFILE
)
829 if (!ieee80211_mle_basic_sta_prof_size_ok(sub
->data
,
833 control
= le16_to_cpu(prof
->control
);
835 if (link_id
!= u16_get_bits(control
,
836 IEEE80211_MLE_STA_CONTROL_LINK_ID
))
839 if (!(control
& IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE
))
842 /* the sub element can be fragmented */
844 cfg80211_defragment_element(sub
,
846 elems_parse
->scratch_pos
,
847 elems_parse
->scratch
+
848 elems_parse
->scratch_len
-
849 elems_parse
->scratch_pos
,
850 IEEE80211_MLE_SUBELEM_FRAGMENT
);
852 if (sta_prof_len
< 0)
855 elems
->prof
= (void *)elems_parse
->scratch_pos
;
856 elems
->sta_prof_len
= sta_prof_len
;
857 elems_parse
->scratch_pos
+= sta_prof_len
;
863 static void ieee80211_mle_parse_link(struct ieee80211_elems_parse
*elems_parse
,
864 struct ieee80211_elems_parse_params
*params
)
866 struct ieee802_11_elems
*elems
= &elems_parse
->elems
;
867 struct ieee80211_mle_per_sta_profile
*prof
;
868 struct ieee80211_elems_parse_params sub
= {
869 .mode
= params
->mode
,
870 .action
= params
->action
,
871 .from_ap
= params
->from_ap
,
874 ssize_t ml_len
= elems
->ml_basic_len
;
875 const struct element
*non_inherit
= NULL
;
878 ml_len
= cfg80211_defragment_element(elems_parse
->ml_basic_elem
,
881 elems_parse
->scratch_pos
,
882 elems_parse
->scratch
+
883 elems_parse
->scratch_len
-
884 elems_parse
->scratch_pos
,
890 elems
->ml_basic
= (const void *)elems_parse
->scratch_pos
;
891 elems
->ml_basic_len
= ml_len
;
892 elems_parse
->scratch_pos
+= ml_len
;
894 if (params
->link_id
== -1)
897 ieee80211_mle_get_sta_prof(elems_parse
, params
->link_id
);
903 /* check if we have the 4 bytes for the fixed part in assoc response */
904 if (elems
->sta_prof_len
< sizeof(*prof
) + prof
->sta_info_len
- 1 + 4) {
906 elems
->sta_prof_len
= 0;
911 * Skip the capability information and the status code that are expected
912 * as part of the station profile in association response frames. Note
913 * the -1 is because the 'sta_info_len' is accounted to as part of the
914 * per-STA profile, but not part of the 'u8 variable[]' portion.
916 sub
.start
= prof
->variable
+ prof
->sta_info_len
- 1 + 4;
917 end
= (const u8
*)prof
+ elems
->sta_prof_len
;
918 sub
.len
= end
- sub
.start
;
920 non_inherit
= cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE
,
922 _ieee802_11_parse_elems_full(&sub
, elems_parse
, non_inherit
);
926 ieee80211_mle_defrag_reconf(struct ieee80211_elems_parse
*elems_parse
)
928 struct ieee802_11_elems
*elems
= &elems_parse
->elems
;
931 ml_len
= cfg80211_defragment_element(elems_parse
->ml_reconf_elem
,
934 elems_parse
->scratch_pos
,
935 elems_parse
->scratch
+
936 elems_parse
->scratch_len
-
937 elems_parse
->scratch_pos
,
941 elems
->ml_reconf
= (void *)elems_parse
->scratch_pos
;
942 elems
->ml_reconf_len
= ml_len
;
943 elems_parse
->scratch_pos
+= ml_len
;
946 struct ieee802_11_elems
*
947 ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params
*params
)
949 struct ieee80211_elems_parse
*elems_parse
;
950 struct ieee802_11_elems
*elems
;
951 const struct element
*non_inherit
= NULL
;
952 u8
*nontransmitted_profile
;
953 int nontransmitted_profile_len
= 0;
954 size_t scratch_len
= 3 * params
->len
;
956 BUILD_BUG_ON(offsetof(typeof(*elems_parse
), elems
) != 0);
958 elems_parse
= kzalloc(struct_size(elems_parse
, scratch
, scratch_len
),
963 elems_parse
->scratch_len
= scratch_len
;
964 elems_parse
->scratch_pos
= elems_parse
->scratch
;
966 elems
= &elems_parse
->elems
;
967 elems
->ie_start
= params
->start
;
968 elems
->total_len
= params
->len
;
970 /* set all TPE entries to unlimited (but invalid) */
971 ieee80211_clear_tpe(&elems
->tpe
);
972 ieee80211_clear_tpe(&elems
->csa_tpe
);
974 nontransmitted_profile
= elems_parse
->scratch_pos
;
975 nontransmitted_profile_len
=
976 ieee802_11_find_bssid_profile(params
->start
, params
->len
,
978 nontransmitted_profile
);
979 elems_parse
->scratch_pos
+= nontransmitted_profile_len
;
980 non_inherit
= cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE
,
981 nontransmitted_profile
,
982 nontransmitted_profile_len
);
984 elems
->crc
= _ieee802_11_parse_elems_full(params
, elems_parse
,
987 /* Override with nontransmitted profile, if found */
988 if (nontransmitted_profile_len
) {
989 struct ieee80211_elems_parse_params sub
= {
990 .mode
= params
->mode
,
991 .start
= nontransmitted_profile
,
992 .len
= nontransmitted_profile_len
,
993 .action
= params
->action
,
994 .link_id
= params
->link_id
,
997 _ieee802_11_parse_elems_full(&sub
, elems_parse
, NULL
);
1000 ieee80211_mle_parse_link(elems_parse
, params
);
1002 ieee80211_mle_defrag_reconf(elems_parse
);
1004 if (elems
->tim
&& !elems
->parse_error
) {
1005 const struct ieee80211_tim_ie
*tim_ie
= elems
->tim
;
1007 elems
->dtim_period
= tim_ie
->dtim_period
;
1008 elems
->dtim_count
= tim_ie
->dtim_count
;
1011 /* Override DTIM period and count if needed */
1012 if (elems
->bssid_index
&&
1013 elems
->bssid_index_len
>=
1014 offsetofend(struct ieee80211_bssid_index
, dtim_period
))
1015 elems
->dtim_period
= elems
->bssid_index
->dtim_period
;
1017 if (elems
->bssid_index
&&
1018 elems
->bssid_index_len
>=
1019 offsetofend(struct ieee80211_bssid_index
, dtim_count
))
1020 elems
->dtim_count
= elems
->bssid_index
->dtim_count
;
1024 EXPORT_SYMBOL_IF_KUNIT(ieee802_11_parse_elems_full
);
1026 int ieee80211_parse_bitrates(enum nl80211_chan_width width
,
1027 const struct ieee80211_supported_band
*sband
,
1028 const u8
*srates
, int srates_len
, u32
*rates
)
1030 u32 rate_flags
= ieee80211_chanwidth_rate_flags(width
);
1031 struct ieee80211_rate
*br
;
1032 int brate
, rate
, i
, j
, count
= 0;
1036 for (i
= 0; i
< srates_len
; i
++) {
1037 rate
= srates
[i
] & 0x7f;
1039 for (j
= 0; j
< sband
->n_bitrates
; j
++) {
1040 br
= &sband
->bitrates
[j
];
1041 if ((rate_flags
& br
->flags
) != rate_flags
)
1044 brate
= DIV_ROUND_UP(br
->bitrate
, 5);
1045 if (brate
== rate
) {