1 /*
2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /*
21 * DOC: Defines scan utility functions
22 */
23
24 #include <wlan_cmn.h>
25 #include <wlan_scan_ucfg_api.h>
26 #include <wlan_scan_utils_api.h>
27 #include <../../core/src/wlan_scan_cache_db.h>
28 #include <../../core/src/wlan_scan_main.h>
29 #include <wlan_reg_services_api.h>
30 #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
31 #include <wlan_mlme_api.h>
32 #endif
33 #ifdef WLAN_FEATURE_11BE_MLO
34 #include <wlan_utility.h>
35 #include "wlan_mlo_mgr_public_structs.h"
36 #include <utils_mlo.h>
37 #endif
38 #include "wlan_psoc_mlme_api.h"
39 #include "reg_services_public_struct.h"
40 #ifdef WLAN_FEATURE_ACTION_OUI
41 #include <wlan_action_oui_main.h>
42 #include <wlan_action_oui_public_struct.h>
43 #endif
44 #include <wlan_crypto_global_api.h>
45
46 #define MAX_IE_LEN 1024
47 #define SHORT_SSID_LEN 4
48 #define NEIGHBOR_AP_LEN 1
49 #define BSS_PARAMS_LEN 1
50
51 const char*
util_scan_get_ev_type_name(enum scan_event_type type)52 util_scan_get_ev_type_name(enum scan_event_type type)
53 {
54 static const char * const event_name[] = {
55 [SCAN_EVENT_TYPE_STARTED] = "STARTED",
56 [SCAN_EVENT_TYPE_COMPLETED] = "COMPLETED",
57 [SCAN_EVENT_TYPE_BSS_CHANNEL] = "HOME_CHANNEL",
58 [SCAN_EVENT_TYPE_FOREIGN_CHANNEL] = "FOREIGN_CHANNEL",
59 [SCAN_EVENT_TYPE_DEQUEUED] = "DEQUEUED",
60 [SCAN_EVENT_TYPE_PREEMPTED] = "PREEMPTED",
61 [SCAN_EVENT_TYPE_START_FAILED] = "START_FAILED",
62 [SCAN_EVENT_TYPE_RESTARTED] = "RESTARTED",
63 [SCAN_EVENT_TYPE_FOREIGN_CHANNEL_EXIT] = "FOREIGN_CHANNEL_EXIT",
64 [SCAN_EVENT_TYPE_SUSPENDED] = "SUSPENDED",
65 [SCAN_EVENT_TYPE_RESUMED] = "RESUMED",
66 [SCAN_EVENT_TYPE_NLO_COMPLETE] = "NLO_COMPLETE",
67 [SCAN_EVENT_TYPE_NLO_MATCH] = "NLO_MATCH",
68 [SCAN_EVENT_TYPE_INVALID] = "INVALID",
69 [SCAN_EVENT_TYPE_GPIO_TIMEOUT] = "GPIO_TIMEOUT",
70 [SCAN_EVENT_TYPE_RADIO_MEASUREMENT_START] =
71 "RADIO_MEASUREMENT_START",
72 [SCAN_EVENT_TYPE_RADIO_MEASUREMENT_END] =
73 "RADIO_MEASUREMENT_END",
74 [SCAN_EVENT_TYPE_BSSID_MATCH] = "BSSID_MATCH",
75 [SCAN_EVENT_TYPE_FOREIGN_CHANNEL_GET_NF] =
76 "FOREIGN_CHANNEL_GET_NF",
77 };
78
79 if (type >= SCAN_EVENT_TYPE_MAX)
80 return "UNKNOWN";
81
82 return event_name[type];
83 }
84
85
86 const char*
util_scan_get_ev_reason_name(enum scan_completion_reason reason)87 util_scan_get_ev_reason_name(enum scan_completion_reason reason)
88 {
89 static const char * const reason_name[] = {
90 [SCAN_REASON_NONE] = "NONE",
91 [SCAN_REASON_COMPLETED] = "COMPLETED",
92 [SCAN_REASON_CANCELLED] = "CANCELLED",
93 [SCAN_REASON_PREEMPTED] = "PREEMPTED",
94 [SCAN_REASON_TIMEDOUT] = "TIMEDOUT",
95 [SCAN_REASON_INTERNAL_FAILURE] = "INTERNAL_FAILURE",
96 [SCAN_REASON_SUSPENDED] = "SUSPENDED",
97 [SCAN_REASON_RUN_FAILED] = "RUN_FAILED",
98 [SCAN_REASON_TERMINATION_FUNCTION] = "TERMINATION_FUNCTION",
99 [SCAN_REASON_MAX_OFFCHAN_RETRIES] = "MAX_OFFCHAN_RETRIES",
100 [SCAN_REASON_DFS_VIOLATION] = "DFS_NOL_VIOLATION",
101 };
102
103 if (reason >= SCAN_REASON_MAX)
104 return "UNKNOWN";
105
106 return reason_name[reason];
107 }
108
109 qdf_time_t
util_get_last_scan_time(struct wlan_objmgr_vdev * vdev)110 util_get_last_scan_time(struct wlan_objmgr_vdev *vdev)
111 {
112 uint8_t pdev_id;
113 struct wlan_scan_obj *scan_obj;
114
115 if (!vdev) {
116 scm_warn("null vdev");
117 QDF_ASSERT(0);
118 return 0;
119 }
120 pdev_id = wlan_scan_vdev_get_pdev_id(vdev);
121 scan_obj = wlan_vdev_get_scan_obj(vdev);
122
123 if (scan_obj)
124 return scan_obj->pdev_info[pdev_id].last_scan_time;
125 else
126 return 0;
127 }
128
129 #ifdef WLAN_FEATURE_11BE_MLO
util_scan_entry_t2lm_len(struct scan_cache_entry * scan_entry)130 uint32_t util_scan_entry_t2lm_len(struct scan_cache_entry *scan_entry)
131 {
132 int i = 0;
133 uint32_t len = 0;
134
135 if (!scan_entry || !scan_entry->ie_list.t2lm[0])
136 return 0;
137
138 for (i = 0; i < WLAN_MAX_T2LM_IE; i++) {
139 if (scan_entry->ie_list.t2lm[i])
140 len += scan_entry->ie_list.t2lm[i][TAG_LEN_POS] +
141 sizeof(struct ie_header);
142 }
143
144 return len;
145 }
146 #endif
147
util_is_rsnxe_h2e_capable(const uint8_t * rsnxe)148 bool util_is_rsnxe_h2e_capable(const uint8_t *rsnxe)
149 {
150 const uint8_t *rsnxe_caps;
151 uint8_t cap_len;
152
153 if (!rsnxe)
154 return false;
155
156 rsnxe_caps = wlan_crypto_parse_rsnxe_ie(rsnxe, &cap_len);
157 if (!rsnxe_caps)
158 return false;
159
160 return *rsnxe_caps & WLAN_CRYPTO_RSNX_CAP_SAE_H2E;
161 }
162
util_scan_entry_sae_h2e_capable(struct scan_cache_entry * scan_entry)163 bool util_scan_entry_sae_h2e_capable(struct scan_cache_entry *scan_entry)
164 {
165 const uint8_t *rsnxe;
166
167 /* If RSN caps are not there, then return false */
168 if (!util_scan_entry_rsn(scan_entry))
169 return false;
170
171 /* If not SAE AKM no need to check H2E capability */
172 if (!WLAN_CRYPTO_IS_AKM_SAE(scan_entry->neg_sec_info.key_mgmt))
173 return false;
174
175 rsnxe = util_scan_entry_rsnxe(scan_entry);
176 return util_is_rsnxe_h2e_capable(rsnxe);
177 }
178
util_scan_scm_freq_to_band(uint16_t freq)179 enum wlan_band util_scan_scm_freq_to_band(uint16_t freq)
180 {
181 if (WLAN_REG_IS_24GHZ_CH_FREQ(freq))
182 return WLAN_BAND_2_4_GHZ;
183
184 return WLAN_BAND_5_GHZ;
185 }
186
util_is_scan_entry_match(struct scan_cache_entry * entry1,struct scan_cache_entry * entry2)187 bool util_is_scan_entry_match(
188 struct scan_cache_entry *entry1,
189 struct scan_cache_entry *entry2)
190 {
191
192 if (entry1->cap_info.wlan_caps.ess !=
193 entry2->cap_info.wlan_caps.ess)
194 return false;
195
196 if (entry1->cap_info.wlan_caps.ess &&
197 !qdf_mem_cmp(entry1->bssid.bytes,
198 entry2->bssid.bytes, QDF_MAC_ADDR_SIZE)) {
199 /* Check for BSS */
200 if (util_is_ssid_match(&entry1->ssid, &entry2->ssid) ||
201 util_scan_is_null_ssid(&entry1->ssid) ||
202 util_scan_is_null_ssid(&entry2->ssid))
203 return true;
204 } else if (entry1->cap_info.wlan_caps.ibss &&
205 (entry1->channel.chan_freq ==
206 entry2->channel.chan_freq)) {
207 /*
208 * Same channel cannot have same SSID for
209 * different IBSS, so no need to check BSSID
210 */
211 if (util_is_ssid_match(
212 &entry1->ssid, &entry2->ssid))
213 return true;
214 } else if (!entry1->cap_info.wlan_caps.ibss &&
215 !entry1->cap_info.wlan_caps.ess &&
216 !qdf_mem_cmp(entry1->bssid.bytes,
217 entry2->bssid.bytes, QDF_MAC_ADDR_SIZE)) {
218 /* In case of P2P devices, ess and ibss will be set to zero */
219 return true;
220 }
221
222 return false;
223 }
224
util_is_pureg_rate(uint8_t * rates,uint8_t nrates)225 static bool util_is_pureg_rate(uint8_t *rates, uint8_t nrates)
226 {
227 static const uint8_t g_rates[] = {12, 18, 24, 36, 48, 72, 96, 108};
228 bool pureg = false;
229 uint8_t i, j;
230
231 for (i = 0; i < nrates; i++) {
232 for (j = 0; j < QDF_ARRAY_SIZE(g_rates); j++) {
233 if (WLAN_RV(rates[i]) == g_rates[j]) {
234 pureg = true;
235 break;
236 }
237 }
238 if (pureg)
239 break;
240 }
241
242 return pureg;
243 }
244
245 #ifdef WLAN_FEATURE_11BE
246 static enum wlan_phymode
util_scan_get_phymode_11be(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params,enum wlan_phymode phymode,uint8_t band_mask)247 util_scan_get_phymode_11be(struct wlan_objmgr_pdev *pdev,
248 struct scan_cache_entry *scan_params,
249 enum wlan_phymode phymode,
250 uint8_t band_mask)
251 {
252 struct wlan_ie_ehtops *eht_ops;
253 uint8_t width;
254
255 eht_ops = (struct wlan_ie_ehtops *)util_scan_entry_ehtop(scan_params);
256 if (!util_scan_entry_ehtcap(scan_params) || !eht_ops)
257 return phymode;
258
259 if (QDF_GET_BITS(eht_ops->ehtop_param,
260 EHTOP_INFO_PRESENT_IDX, EHTOP_INFO_PRESENT_BITS)) {
261 width = QDF_GET_BITS(eht_ops->control,
262 EHTOP_INFO_CHAN_WIDTH_IDX,
263 EHTOP_INFO_CHAN_WIDTH_BITS);
264 switch (width) {
265 case WLAN_EHT_CHWIDTH_20:
266 phymode = WLAN_PHYMODE_11BEA_EHT20;
267 break;
268 case WLAN_EHT_CHWIDTH_40:
269 phymode = WLAN_PHYMODE_11BEA_EHT40;
270 break;
271 case WLAN_EHT_CHWIDTH_80:
272 phymode = WLAN_PHYMODE_11BEA_EHT80;
273 break;
274 case WLAN_EHT_CHWIDTH_160:
275 phymode = WLAN_PHYMODE_11BEA_EHT160;
276 break;
277 case WLAN_EHT_CHWIDTH_320:
278 phymode = WLAN_PHYMODE_11BEA_EHT320;
279 break;
280 default:
281 scm_debug("Invalid eht_ops width: %d", width);
282 phymode = WLAN_PHYMODE_11BEA_EHT20;
283 break;
284 }
285 } else {
286 switch (phymode) {
287 case WLAN_PHYMODE_11AXA_HE20:
288 phymode = WLAN_PHYMODE_11BEA_EHT20;
289 break;
290 case WLAN_PHYMODE_11AXG_HE20:
291 phymode = WLAN_PHYMODE_11BEG_EHT20;
292 break;
293 case WLAN_PHYMODE_11AXA_HE40:
294 phymode = WLAN_PHYMODE_11BEA_EHT40;
295 break;
296 case WLAN_PHYMODE_11AXG_HE40:
297 phymode = WLAN_PHYMODE_11BEG_EHT40;
298 break;
299 case WLAN_PHYMODE_11AXA_HE80:
300 phymode = WLAN_PHYMODE_11BEA_EHT80;
301 break;
302 case WLAN_PHYMODE_11AXA_HE160:
303 phymode = WLAN_PHYMODE_11BEA_EHT160;
304 break;
305 default:
306 break;
307 }
308 }
309
310 if (QDF_GET_BITS(eht_ops->ehtop_param,
311 EHTOP_INFO_PRESENT_IDX, EHTOP_INFO_PRESENT_BITS)) {
312 scan_params->channel.cfreq0 =
313 wlan_reg_chan_band_to_freq(pdev,
314 eht_ops->ccfs0,
315 band_mask);
316 scan_params->channel.cfreq1 =
317 wlan_reg_chan_band_to_freq(pdev,
318 eht_ops->ccfs1,
319 band_mask);
320 }
321
322 if (QDF_GET_BITS(eht_ops->ehtop_param,
323 EHTOP_PARAM_DISABLED_SC_BITMAP_PRESENT_IDX,
324 EHTOP_PARAM_DISABLED_SC_BITMAP_PRESENT_BITS)) {
325 scan_params->channel.puncture_bitmap =
326 QDF_GET_BITS(eht_ops->disabled_sub_chan_bitmap[0],
327 0, 8);
328 scan_params->channel.puncture_bitmap |=
329 QDF_GET_BITS(eht_ops->disabled_sub_chan_bitmap[1],
330 0, 8) << 8;
331 } else {
332 scan_params->channel.puncture_bitmap = 0;
333 }
334
335 return phymode;
336 }
337 #else
338 static enum wlan_phymode
util_scan_get_phymode_11be(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params,enum wlan_phymode phymode,uint8_t band_mask)339 util_scan_get_phymode_11be(struct wlan_objmgr_pdev *pdev,
340 struct scan_cache_entry *scan_params,
341 enum wlan_phymode phymode,
342 uint8_t band_mask)
343 {
344 return phymode;
345 }
346 #endif
347
348 #ifdef CONFIG_BAND_6GHZ
util_scan_get_he_6g_params(uint8_t * he_ops)349 static struct he_oper_6g_param *util_scan_get_he_6g_params(uint8_t *he_ops)
350 {
351 uint8_t len;
352 uint32_t he_oper_params;
353
354 if (!he_ops)
355 return NULL;
356
357 len = he_ops[1];
358 he_ops += sizeof(struct ie_header);
359
360 if (len < WLAN_HEOP_FIXED_PARAM_LENGTH)
361 return NULL;
362
363 /* element id extension */
364 he_ops++;
365 len--;
366
367 he_oper_params = LE_READ_4(he_ops);
368 if (!(he_oper_params & WLAN_HEOP_6GHZ_INFO_PRESENT_MASK))
369 return NULL;
370
371 /* fixed params - element id extension */
372 he_ops += WLAN_HEOP_FIXED_PARAM_LENGTH - 1;
373 len -= WLAN_HEOP_FIXED_PARAM_LENGTH - 1;
374
375 if (!len)
376 return NULL;
377
378 /* vht oper params */
379 if (he_oper_params & WLAN_HEOP_VHTOP_PRESENT_MASK) {
380 if (len < WLAN_HEOP_VHTOP_LENGTH)
381 return NULL;
382 he_ops += WLAN_HEOP_VHTOP_LENGTH;
383 len -= WLAN_HEOP_VHTOP_LENGTH;
384 }
385
386 if (!len)
387 return NULL;
388
389 if (he_oper_params & WLAN_HEOP_CO_LOCATED_BSS_MASK) {
390 he_ops += WLAN_HEOP_CO_LOCATED_BSS_LENGTH;
391 len -= WLAN_HEOP_CO_LOCATED_BSS_LENGTH;
392 }
393
394 if (len < sizeof(struct he_oper_6g_param))
395 return NULL;
396
397 return (struct he_oper_6g_param *)he_ops;
398 }
399
400 #ifdef WLAN_FEATURE_11BE
401 /*
402 * util_scan_is_out_of_band_leak_eht() - Check if eht beacon out of BSS BW
403 * @pdev: pointer to pdev.
404 * @scan_params: scan entry generated by beacon/probe rsp
405 * @band_mask: band mask of frequency beacon/probe rsp received
406 * @current_freq: frequency beacon/probe rsp received
407 *
408 * 1. If BSS BW <= 80MHz
409 * If Absolute value of (Current Channel Channel Center Frequency Segment 0) <=
410 * BSS BW/2 then eht beacon in BSS operating BW
411 * else eht beacon out of BSS operating BW
412 *
413 * 2. If BSS BW > 80MHz
414 * If Absolute value of (Current Channel Channel Center Frequency Segment 1) <=
415 * BSS BW/2 then eht beacon in BSS operating BW
416 * else eht beacon out of BSS operating BW
417 *
418 * Return: bool, whether eht beacon out of BSS operating BW
419 */
420 static bool
util_scan_is_out_of_band_leak_eht(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params,uint8_t band_mask,qdf_freq_t current_freq)421 util_scan_is_out_of_band_leak_eht(struct wlan_objmgr_pdev *pdev,
422 struct scan_cache_entry *scan_params,
423 uint8_t band_mask,
424 qdf_freq_t current_freq)
425 {
426 struct wlan_ie_ehtops *eht_ops;
427 uint8_t ch_width;
428 uint32_t bw;
429 uint32_t freq_diff;
430 qdf_freq_t freq_seg0;
431 qdf_freq_t freq_seg1;
432
433 eht_ops = (struct wlan_ie_ehtops *)util_scan_entry_ehtop(scan_params);
434 if (!util_scan_entry_ehtcap(scan_params) || !eht_ops)
435 return false;
436
437 if (!QDF_GET_BITS(eht_ops->ehtop_param,
438 EHTOP_INFO_PRESENT_IDX, EHTOP_INFO_PRESENT_BITS))
439 return false;
440
441 ch_width = QDF_GET_BITS(eht_ops->control,
442 EHTOP_INFO_CHAN_WIDTH_IDX,
443 EHTOP_INFO_CHAN_WIDTH_BITS);
444 freq_seg0 = wlan_reg_chan_band_to_freq(pdev, eht_ops->ccfs0,
445 band_mask);
446 freq_seg1 = wlan_reg_chan_band_to_freq(pdev, eht_ops->ccfs1,
447 band_mask);
448 if (ch_width == WLAN_EHT_CHWIDTH_320)
449 bw = BW_320_MHZ;
450 else if (ch_width == WLAN_EHT_CHWIDTH_160)
451 bw = BW_160_MHZ;
452 else if (ch_width == WLAN_EHT_CHWIDTH_80)
453 bw = BW_80_MHZ;
454 else if (ch_width == WLAN_EHT_CHWIDTH_40)
455 bw = BW_40_MHZ;
456 else if (ch_width == WLAN_EHT_CHWIDTH_20)
457 bw = BW_20_MHZ;
458 else
459 bw = BW_20_MHZ;
460
461 if (bw <= BW_80_MHZ)
462 freq_diff = abs(freq_seg0 - current_freq);
463 else
464 freq_diff = abs(freq_seg1 - current_freq);
465 if (freq_diff <= bw / 2)
466 return false;
467
468 scm_debug("Leaked freq:%u ch width:%u freq0:%u freq1:%u",
469 current_freq, bw, freq_seg0, freq_seg1);
470 return true;
471 }
472 #else
473 static bool
util_scan_is_out_of_band_leak_eht(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params,uint8_t band_mask,qdf_freq_t current_freq)474 util_scan_is_out_of_band_leak_eht(struct wlan_objmgr_pdev *pdev,
475 struct scan_cache_entry *scan_params,
476 uint8_t band_mask,
477 qdf_freq_t current_freq)
478 {
479 return false;
480 }
481 #endif
482
483 /*
484 * util_scan_is_out_of_band_leak_he() - Check if HE beacon out of BSS BW
485 * @pdev: pointer to pdev.
486 * @he_6g_params: HE 6 GHz params
487 * @band_mask: band mask of frequency beacon/probe rsp received
488 * @current_freq: frequency beacon/probe rsp received
489 *
490 * 1. If BSS BW <= 80MHz
491 * If Absolute value of (Current Channel Channel Center Frequency Segment 0) <=
492 * BSS BW/2 then HE beacon in BSS operating BW
493 *
494 * 2. If BSS BW is 160MHz
495 * If Absolute value of (Current Channel Channel Center Frequency Segment 1) <=
496 * BSS BW/2 then HE beacon in BSS operating BW
497 *
498 * 3. If BSS BW is 80+80MHz
499 * If absolute value of (Current Channel - Channel Center Frequency Segment 0)
500 * <= 40 or absolute value of (Current Channel - Channel Center Frequency
501 * Segment 1) <= 40, then HE beacon in BSS operating BW
502 *
503 * Return: bool, whether HE beacon out of BSS operating BW
504 */
505 static bool
util_scan_is_out_of_band_leak_he(struct wlan_objmgr_pdev * pdev,struct he_oper_6g_param * he_6g_params,uint8_t band_mask,qdf_freq_t current_freq)506 util_scan_is_out_of_band_leak_he(struct wlan_objmgr_pdev *pdev,
507 struct he_oper_6g_param *he_6g_params,
508 uint8_t band_mask,
509 qdf_freq_t current_freq)
510 {
511 uint8_t ch_width;
512 uint32_t bw;
513 uint32_t freq_diff;
514 qdf_freq_t freq_seg0;
515 qdf_freq_t freq_seg1;
516
517 ch_width = he_6g_params->width;
518 freq_seg0 = wlan_reg_chan_band_to_freq(pdev,
519 he_6g_params->chan_freq_seg0,
520 band_mask);
521 freq_seg1 = wlan_reg_chan_band_to_freq(pdev,
522 he_6g_params->chan_freq_seg1,
523 band_mask);
524 if (ch_width == WLAN_HE_6GHZ_CHWIDTH_160_80_80)
525 bw = BW_160_MHZ;
526 else if (ch_width == WLAN_HE_6GHZ_CHWIDTH_80)
527 bw = BW_80_MHZ;
528 else if (ch_width == WLAN_HE_6GHZ_CHWIDTH_40)
529 bw = BW_40_MHZ;
530 else if (ch_width == WLAN_HE_6GHZ_CHWIDTH_20)
531 bw = BW_20_MHZ;
532 else
533 bw = BW_20_MHZ;
534
535 if (bw <= BW_80_MHZ) {
536 freq_diff = abs(freq_seg0 - current_freq);
537 if (freq_diff <= bw / 2)
538 return false;
539 } else if (WLAN_IS_HE160(he_6g_params)) {
540 freq_diff = abs(freq_seg1 - current_freq);
541 if (freq_diff <= bw / 2)
542 return false;
543 } else if (WLAN_IS_HE80_80(he_6g_params)) {
544 freq_diff = abs(freq_seg0 - current_freq);
545 if (freq_diff <= BW_40_MHZ)
546 return false;
547 freq_diff = abs(freq_seg1 - current_freq);
548 if (freq_diff <= BW_40_MHZ)
549 return false;
550 }
551
552 scm_debug("Leaked freq:%u ch width:%u freq0:%u freq1:%u",
553 current_freq, bw, freq_seg0, freq_seg1);
554
555 return true;
556 }
557
558 /*
559 * util_scan_get_chan_from_he_6g_params() - Get chan info from 6 GHz param
560 * @pdev: pointer to pdev.
561 * @scan_params: scan entry generated by beacon/probe rsp
562 * @chan_freq: output parameter, primary freq from 6 GHz he params
563 * @is_6g_dup_bcon: output parameter, bool, if false, invalid 6g duplicated
564 beacon out of BSS operating BW or not duplicated beacon, can drop if
565 channel mismatch
566 * @band_mask: band mask of frequency beacon/probe rsp received
567 * @current_freq: frequency beacon/probe rsp received
568 *
569 * Return: QDF_STATUS
570 */
571 static QDF_STATUS
util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params,qdf_freq_t * chan_freq,bool * is_6g_dup_bcon,uint8_t band_mask,qdf_freq_t current_freq)572 util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev *pdev,
573 struct scan_cache_entry *scan_params,
574 qdf_freq_t *chan_freq,
575 bool *is_6g_dup_bcon, uint8_t band_mask,
576 qdf_freq_t current_freq)
577 {
578 struct he_oper_6g_param *he_6g_params;
579 uint8_t *he_ops;
580 struct wlan_scan_obj *scan_obj;
581 struct wlan_objmgr_psoc *psoc;
582 bool is_out_of_band_leak = true;
583
584 psoc = wlan_pdev_get_psoc(pdev);
585 if (!psoc) {
586 scm_err("psoc is NULL");
587 return QDF_STATUS_E_INVAL;
588 }
589
590 scan_obj = wlan_psoc_get_scan_obj(psoc);
591 if (!scan_obj) {
592 scm_err("scan_obj is NULL");
593 return QDF_STATUS_E_INVAL;
594 }
595
596 *is_6g_dup_bcon = false;
597
598 he_ops = util_scan_entry_heop(scan_params);
599 if (!util_scan_entry_hecap(scan_params) || !he_ops)
600 return QDF_STATUS_SUCCESS;
601
602 he_6g_params = util_scan_get_he_6g_params(he_ops);
603 if (!he_6g_params)
604 return QDF_STATUS_SUCCESS;
605
606 *chan_freq = wlan_reg_chan_band_to_freq(pdev,
607 he_6g_params->primary_channel,
608 band_mask);
609 if (scan_obj->drop_bcn_on_invalid_freq &&
610 !wlan_reg_is_freq_enabled(pdev, *chan_freq, REG_BEST_PWR_MODE)) {
611 scm_debug_rl(QDF_MAC_ADDR_FMT": Drop as invalid channel %d freq %d in HE 6Ghz params",
612 QDF_MAC_ADDR_REF(scan_params->bssid.bytes),
613 he_6g_params->primary_channel, *chan_freq);
614 return QDF_STATUS_E_INVAL;
615 }
616
617 if (!he_6g_params->duplicate_beacon) {
618 *is_6g_dup_bcon = false;
619 return QDF_STATUS_SUCCESS;
620 }
621 is_out_of_band_leak =
622 util_scan_is_out_of_band_leak_eht(pdev, scan_params, band_mask,
623 current_freq);
624 if (is_out_of_band_leak) {
625 *is_6g_dup_bcon = false;
626 return QDF_STATUS_SUCCESS;
627 }
628 is_out_of_band_leak =
629 util_scan_is_out_of_band_leak_he(pdev, he_6g_params, band_mask,
630 current_freq);
631 if (is_out_of_band_leak) {
632 *is_6g_dup_bcon = false;
633 return QDF_STATUS_SUCCESS;
634 }
635
636 *is_6g_dup_bcon = true;
637
638 return QDF_STATUS_SUCCESS;
639 }
640
641 static enum wlan_phymode
util_scan_get_phymode_6g(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params)642 util_scan_get_phymode_6g(struct wlan_objmgr_pdev *pdev,
643 struct scan_cache_entry *scan_params)
644 {
645 struct he_oper_6g_param *he_6g_params;
646 enum wlan_phymode phymode = WLAN_PHYMODE_11AXA_HE20;
647 uint8_t *he_ops;
648 uint8_t band_mask = BIT(REG_BAND_6G);
649
650 he_ops = util_scan_entry_heop(scan_params);
651 if (!util_scan_entry_hecap(scan_params) || !he_ops)
652 return phymode;
653
654 he_6g_params = util_scan_get_he_6g_params(he_ops);
655 if (!he_6g_params)
656 return phymode;
657
658 switch (he_6g_params->width) {
659 case WLAN_HE_6GHZ_CHWIDTH_20:
660 phymode = WLAN_PHYMODE_11AXA_HE20;
661 break;
662 case WLAN_HE_6GHZ_CHWIDTH_40:
663 phymode = WLAN_PHYMODE_11AXA_HE40;
664 break;
665 case WLAN_HE_6GHZ_CHWIDTH_80:
666 phymode = WLAN_PHYMODE_11AXA_HE80;
667 break;
668 case WLAN_HE_6GHZ_CHWIDTH_160_80_80:
669 if (WLAN_IS_HE80_80(he_6g_params))
670 phymode = WLAN_PHYMODE_11AXA_HE80_80;
671 else if (WLAN_IS_HE160(he_6g_params))
672 phymode = WLAN_PHYMODE_11AXA_HE160;
673 else
674 phymode = WLAN_PHYMODE_11AXA_HE80;
675 break;
676 default:
677 scm_err("Invalid he_6g_params width: %d", he_6g_params->width);
678 phymode = WLAN_PHYMODE_11AXA_HE20;
679 break;
680 }
681
682 if (he_6g_params->chan_freq_seg0)
683 scan_params->channel.cfreq0 =
684 wlan_reg_chan_band_to_freq(pdev,
685 he_6g_params->chan_freq_seg0,
686 band_mask);
687 if (he_6g_params->chan_freq_seg1)
688 scan_params->channel.cfreq1 =
689 wlan_reg_chan_band_to_freq(pdev,
690 he_6g_params->chan_freq_seg1,
691 band_mask);
692
693 phymode = util_scan_get_phymode_11be(pdev, scan_params,
694 phymode, band_mask);
695
696 return phymode;
697 }
698
699 uint8_t
util_scan_get_6g_oper_channel(uint8_t * he_op_ie)700 util_scan_get_6g_oper_channel(uint8_t *he_op_ie)
701 {
702 struct he_oper_6g_param *he_6g_params;
703
704 he_6g_params = util_scan_get_he_6g_params(he_op_ie);
705 if (!he_6g_params)
706 return 0;
707
708 return he_6g_params->primary_channel;
709 }
710
711 #else
712 static QDF_STATUS
util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params,qdf_freq_t * chan_freq,bool * is_6g_dup_bcon,uint8_t band_mask,qdf_freq_t current_freq)713 util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev *pdev,
714 struct scan_cache_entry *scan_params,
715 qdf_freq_t *chan_freq,
716 bool *is_6g_dup_bcon,
717 uint8_t band_mask,
718 qdf_freq_t current_freq)
719 {
720 return QDF_STATUS_SUCCESS;
721 }
722 static inline enum wlan_phymode
util_scan_get_phymode_6g(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params)723 util_scan_get_phymode_6g(struct wlan_objmgr_pdev *pdev,
724 struct scan_cache_entry *scan_params)
725 {
726 return WLAN_PHYMODE_AUTO;
727 }
728 #endif
729
730 static inline
util_scan_ccfs0_from_htinfo(struct wlan_ie_htinfo_cmn * htinfo,uint32_t primary_chan_freq)731 uint32_t util_scan_ccfs0_from_htinfo(struct wlan_ie_htinfo_cmn *htinfo,
732 uint32_t primary_chan_freq)
733 {
734 if (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_ABOVE)
735 return primary_chan_freq + WLAN_CHAN_SPACING_20MHZ / 2;
736 else if (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_BELOW)
737 return primary_chan_freq - WLAN_CHAN_SPACING_20MHZ / 2;
738
739 return 0;
740 }
741
742 static enum wlan_phymode
util_scan_get_phymode_5g(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params)743 util_scan_get_phymode_5g(struct wlan_objmgr_pdev *pdev,
744 struct scan_cache_entry *scan_params)
745 {
746 enum wlan_phymode phymode = WLAN_PHYMODE_AUTO;
747 uint16_t ht_cap = 0;
748 struct htcap_cmn_ie *htcap;
749 struct wlan_ie_htinfo_cmn *htinfo;
750 struct wlan_ie_vhtop *vhtop;
751 uint8_t band_mask = BIT(REG_BAND_5G);
752
753 htcap = (struct htcap_cmn_ie *)
754 util_scan_entry_htcap(scan_params);
755 htinfo = (struct wlan_ie_htinfo_cmn *)
756 util_scan_entry_htinfo(scan_params);
757 vhtop = (struct wlan_ie_vhtop *)
758 util_scan_entry_vhtop(scan_params);
759
760 if (!(htcap && htinfo))
761 return WLAN_PHYMODE_11A;
762
763 if (htcap)
764 ht_cap = le16toh(htcap->hc_cap);
765
766 if ((ht_cap & WLAN_HTCAP_C_CHWIDTH40) &&
767 (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_ABOVE ||
768 htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_BELOW))
769 phymode = WLAN_PHYMODE_11NA_HT40;
770 else
771 phymode = WLAN_PHYMODE_11NA_HT20;
772
773 scan_params->channel.cfreq0 =
774 util_scan_ccfs0_from_htinfo(htinfo,
775 scan_params->channel.chan_freq);
776
777 if (util_scan_entry_vhtcap(scan_params) && vhtop) {
778 switch (vhtop->vht_op_chwidth) {
779 case WLAN_VHTOP_CHWIDTH_2040:
780 if (phymode == WLAN_PHYMODE_11NA_HT40)
781 phymode = WLAN_PHYMODE_11AC_VHT40;
782 else
783 phymode = WLAN_PHYMODE_11AC_VHT20;
784 break;
785 case WLAN_VHTOP_CHWIDTH_80:
786 if (WLAN_IS_REVSIG_VHT80_80(vhtop))
787 phymode = WLAN_PHYMODE_11AC_VHT80_80;
788 else if (WLAN_IS_REVSIG_VHT160(vhtop))
789 phymode = WLAN_PHYMODE_11AC_VHT160;
790 else
791 phymode = WLAN_PHYMODE_11AC_VHT80;
792 break;
793 case WLAN_VHTOP_CHWIDTH_160:
794 phymode = WLAN_PHYMODE_11AC_VHT160;
795 break;
796 case WLAN_VHTOP_CHWIDTH_80_80:
797 phymode = WLAN_PHYMODE_11AC_VHT80_80;
798 break;
799 default:
800 scm_debug("bad channel: %d",
801 vhtop->vht_op_chwidth);
802 phymode = WLAN_PHYMODE_11AC_VHT20;
803 break;
804 }
805 if (vhtop->vht_op_ch_freq_seg1)
806 scan_params->channel.cfreq0 =
807 wlan_reg_chan_band_to_freq(pdev,
808 vhtop->vht_op_ch_freq_seg1,
809 band_mask);
810 if (vhtop->vht_op_ch_freq_seg2)
811 scan_params->channel.cfreq1 =
812 wlan_reg_chan_band_to_freq(pdev,
813 vhtop->vht_op_ch_freq_seg2,
814 band_mask);
815 }
816
817 if (!util_scan_entry_hecap(scan_params))
818 return phymode;
819
820 /* for 5Ghz Check for HE, only if VHT cap and HE cap are present */
821 if (!IS_WLAN_PHYMODE_VHT(phymode))
822 return phymode;
823
824 switch (phymode) {
825 case WLAN_PHYMODE_11AC_VHT20:
826 phymode = WLAN_PHYMODE_11AXA_HE20;
827 break;
828 case WLAN_PHYMODE_11AC_VHT40:
829 phymode = WLAN_PHYMODE_11AXA_HE40;
830 break;
831 case WLAN_PHYMODE_11AC_VHT80:
832 phymode = WLAN_PHYMODE_11AXA_HE80;
833 break;
834 case WLAN_PHYMODE_11AC_VHT160:
835 phymode = WLAN_PHYMODE_11AXA_HE160;
836 break;
837 case WLAN_PHYMODE_11AC_VHT80_80:
838 phymode = WLAN_PHYMODE_11AXA_HE80_80;
839 break;
840 default:
841 phymode = WLAN_PHYMODE_11AXA_HE20;
842 break;
843 }
844
845 phymode = util_scan_get_phymode_11be(pdev, scan_params,
846 phymode, band_mask);
847
848 return phymode;
849 }
850
851 #ifdef WLAN_FEATURE_11BE
852 static enum wlan_phymode
util_scan_get_phymode_2g_11be(struct scan_cache_entry * scan_params,enum wlan_phymode phymode)853 util_scan_get_phymode_2g_11be(struct scan_cache_entry *scan_params,
854 enum wlan_phymode phymode)
855 {
856 if (!util_scan_entry_ehtcap(scan_params))
857 return phymode;
858
859 if (phymode == WLAN_PHYMODE_11AXG_HE40PLUS)
860 phymode = WLAN_PHYMODE_11BEG_EHT40PLUS;
861 else if (phymode == WLAN_PHYMODE_11AXG_HE40MINUS)
862 phymode = WLAN_PHYMODE_11BEG_EHT40MINUS;
863 else
864 phymode = WLAN_PHYMODE_11BEG_EHT20;
865
866 return phymode;
867 }
868 #else
869 static enum wlan_phymode
util_scan_get_phymode_2g_11be(struct scan_cache_entry * scan_params,enum wlan_phymode phymode)870 util_scan_get_phymode_2g_11be(struct scan_cache_entry *scan_params,
871 enum wlan_phymode phymode)
872 {
873 return phymode;
874 }
875 #endif
876
877 static enum wlan_phymode
util_scan_get_phymode_2g(struct scan_cache_entry * scan_params)878 util_scan_get_phymode_2g(struct scan_cache_entry *scan_params)
879 {
880 enum wlan_phymode phymode = WLAN_PHYMODE_AUTO;
881 uint16_t ht_cap = 0;
882 struct htcap_cmn_ie *htcap;
883 struct wlan_ie_htinfo_cmn *htinfo;
884 struct wlan_ie_vhtop *vhtop;
885
886 htcap = (struct htcap_cmn_ie *)
887 util_scan_entry_htcap(scan_params);
888 htinfo = (struct wlan_ie_htinfo_cmn *)
889 util_scan_entry_htinfo(scan_params);
890 vhtop = (struct wlan_ie_vhtop *)
891 util_scan_entry_vhtop(scan_params);
892
893 if (htcap)
894 ht_cap = le16toh(htcap->hc_cap);
895
896 if (htcap && htinfo) {
897 if ((ht_cap & WLAN_HTCAP_C_CHWIDTH40) &&
898 (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_ABOVE))
899 phymode = WLAN_PHYMODE_11NG_HT40PLUS;
900 else if ((ht_cap & WLAN_HTCAP_C_CHWIDTH40) &&
901 (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_BELOW))
902 phymode = WLAN_PHYMODE_11NG_HT40MINUS;
903 else
904 phymode = WLAN_PHYMODE_11NG_HT20;
905 } else if (util_scan_entry_xrates(scan_params)) {
906 /* only 11G stations will have more than 8 rates */
907 phymode = WLAN_PHYMODE_11G;
908 } else {
909 /* Some mischievous g-only APs do not set extended rates */
910 if (util_scan_entry_rates(scan_params)) {
911 if (util_is_pureg_rate(&scan_params->ie_list.rates[2],
912 scan_params->ie_list.rates[1]))
913 phymode = WLAN_PHYMODE_11G;
914 else
915 phymode = WLAN_PHYMODE_11B;
916 } else {
917 phymode = WLAN_PHYMODE_11B;
918 }
919 }
920
921 /* Check for VHT only if HT cap is present */
922 if (!IS_WLAN_PHYMODE_HT(phymode))
923 return phymode;
924
925 scan_params->channel.cfreq0 =
926 util_scan_ccfs0_from_htinfo(htinfo,
927 scan_params->channel.chan_freq);
928
929 if (util_scan_entry_vhtcap(scan_params) && vhtop) {
930 switch (vhtop->vht_op_chwidth) {
931 case WLAN_VHTOP_CHWIDTH_2040:
932 if (phymode == WLAN_PHYMODE_11NG_HT40PLUS)
933 phymode = WLAN_PHYMODE_11AC_VHT40PLUS_2G;
934 else if (phymode == WLAN_PHYMODE_11NG_HT40MINUS)
935 phymode = WLAN_PHYMODE_11AC_VHT40MINUS_2G;
936 else
937 phymode = WLAN_PHYMODE_11AC_VHT20_2G;
938
939 break;
940 default:
941 scm_info("bad vht_op_chwidth: %d",
942 vhtop->vht_op_chwidth);
943 phymode = WLAN_PHYMODE_11AC_VHT20_2G;
944 break;
945 }
946 }
947
948 if (!util_scan_entry_hecap(scan_params))
949 return phymode;
950
951 if (phymode == WLAN_PHYMODE_11AC_VHT40PLUS_2G ||
952 phymode == WLAN_PHYMODE_11NG_HT40PLUS)
953 phymode = WLAN_PHYMODE_11AXG_HE40PLUS;
954 else if (phymode == WLAN_PHYMODE_11AC_VHT40MINUS_2G ||
955 phymode == WLAN_PHYMODE_11NG_HT40MINUS)
956 phymode = WLAN_PHYMODE_11AXG_HE40MINUS;
957 else
958 phymode = WLAN_PHYMODE_11AXG_HE20;
959
960 phymode = util_scan_get_phymode_2g_11be(scan_params, phymode);
961
962 return phymode;
963 }
964
965 static enum wlan_phymode
util_scan_get_phymode(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params)966 util_scan_get_phymode(struct wlan_objmgr_pdev *pdev,
967 struct scan_cache_entry *scan_params)
968 {
969 if (WLAN_REG_IS_24GHZ_CH_FREQ(scan_params->channel.chan_freq))
970 return util_scan_get_phymode_2g(scan_params);
971 else if (WLAN_REG_IS_6GHZ_CHAN_FREQ(scan_params->channel.chan_freq))
972 return util_scan_get_phymode_6g(pdev, scan_params);
973 else
974 return util_scan_get_phymode_5g(pdev, scan_params);
975 }
976
977 static QDF_STATUS
util_scan_parse_chan_switch_wrapper_ie(struct scan_cache_entry * scan_params,struct ie_header * sub_ie,qdf_size_t sub_ie_len)978 util_scan_parse_chan_switch_wrapper_ie(struct scan_cache_entry *scan_params,
979 struct ie_header *sub_ie, qdf_size_t sub_ie_len)
980 {
981 /* Walk through to check nothing is malformed */
982 while (sub_ie_len >= sizeof(struct ie_header)) {
983 /* At least one more header is present */
984 sub_ie_len -= sizeof(struct ie_header);
985
986 if (sub_ie->ie_len == 0) {
987 sub_ie += 1;
988 continue;
989 }
990 if (sub_ie_len < sub_ie->ie_len) {
991 scm_debug_rl(QDF_MAC_ADDR_FMT": Incomplete corrupted IE:%x",
992 QDF_MAC_ADDR_REF(scan_params->bssid.bytes),
993 WLAN_ELEMID_CHAN_SWITCH_WRAP);
994 return QDF_STATUS_E_INVAL;
995 }
996 switch (sub_ie->ie_id) {
997 case WLAN_ELEMID_COUNTRY:
998 if (sub_ie->ie_len < WLAN_COUNTRY_IE_MIN_LEN)
999 return QDF_STATUS_E_INVAL;
1000 scan_params->ie_list.country = (uint8_t *)sub_ie;
1001 break;
1002 case WLAN_ELEMID_WIDE_BAND_CHAN_SWITCH:
1003 if (sub_ie->ie_len < WLAN_WIDE_BW_CHAN_SWITCH_IE_LEN)
1004 return QDF_STATUS_E_INVAL;
1005 scan_params->ie_list.widebw = (uint8_t *)sub_ie;
1006 break;
1007 case WLAN_ELEMID_VHT_TX_PWR_ENVLP:
1008 if (sub_ie->ie_len > WLAN_TPE_IE_MAX_LEN)
1009 return QDF_STATUS_E_INVAL;
1010 scan_params->ie_list.txpwrenvlp = (uint8_t *)sub_ie;
1011 break;
1012 #ifdef WLAN_FEATURE_11BE
1013 case WLAN_EXTN_ELEMID_BW_IND:
1014 if (sub_ie->ie_len > WLAN_BW_IND_IE_MAX_LEN)
1015 return QDF_STATUS_E_INVAL;
1016 scan_params->ie_list.bw_ind = (uint8_t *)sub_ie;
1017 break;
1018 #endif
1019 }
1020 /* Consume sub info element */
1021 sub_ie_len -= sub_ie->ie_len;
1022 /* go to next Sub IE */
1023 sub_ie = (struct ie_header *)
1024 (((uint8_t *) sub_ie) +
1025 sizeof(struct ie_header) + sub_ie->ie_len);
1026 }
1027
1028 return QDF_STATUS_SUCCESS;
1029 }
1030
1031 bool
util_scan_is_hidden_ssid(struct ie_ssid * ssid)1032 util_scan_is_hidden_ssid(struct ie_ssid *ssid)
1033 {
1034 uint8_t i;
1035
1036 /*
1037 * We flag this as Hidden SSID if the Length is 0
1038 * of the SSID only contains 0's
1039 */
1040 if (!ssid || !ssid->ssid_len)
1041 return true;
1042
1043 for (i = 0; i < ssid->ssid_len; i++)
1044 if (ssid->ssid[i] != 0)
1045 return false;
1046
1047 /* All 0's */
1048 return true;
1049 }
1050
1051 #ifdef WLAN_FEATURE_11BE_MLO
util_scan_update_rnr_mld(struct rnr_bss_info * rnr,uint8_t * data,uint8_t tbtt_info_length)1052 static void util_scan_update_rnr_mld(struct rnr_bss_info *rnr, uint8_t *data,
1053 uint8_t tbtt_info_length)
1054 {
1055 bool mld_info_present = false;
1056
1057 switch (tbtt_info_length) {
1058 case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD_MLD_PARAM:
1059 qdf_mem_copy(&rnr->mld_info, &data[13],
1060 sizeof(struct rnr_mld_info));
1061 mld_info_present = true;
1062 break;
1063 };
1064
1065 rnr->mld_info_valid = mld_info_present;
1066 }
1067 #else
1068 static inline void
util_scan_update_rnr_mld(struct rnr_bss_info * rnr,uint8_t * data,uint8_t tbtt_info_length)1069 util_scan_update_rnr_mld(struct rnr_bss_info *rnr, uint8_t *data,
1070 uint8_t tbtt_info_length)
1071 {
1072 }
1073 #endif
1074
1075 static QDF_STATUS
util_scan_update_rnr(struct rnr_bss_info * rnr,struct neighbor_ap_info_field * ap_info,uint8_t * data)1076 util_scan_update_rnr(struct rnr_bss_info *rnr,
1077 struct neighbor_ap_info_field *ap_info,
1078 uint8_t *data)
1079 {
1080 uint8_t tbtt_info_length;
1081
1082 tbtt_info_length = ap_info->tbtt_header.tbtt_info_length;
1083
1084 /*
1085 * Max TBTT sub-element length in RNR IE is 255 bytes and AP can send
1086 * data above defined length and the bytes in excess to this length
1087 * shall be treated as reserved.
1088 *
1089 * Limit the TBTT sub-element read operation to current supported
1090 * length i.e TBTT_NEIGHBOR_AP_PARAM_MAX
1091 */
1092 if (tbtt_info_length > TBTT_NEIGHBOR_AP_PARAM_MAX)
1093 tbtt_info_length = TBTT_NEIGHBOR_AP_PARAM_MAX;
1094
1095 switch (tbtt_info_length) {
1096 case TBTT_NEIGHBOR_AP_OFFSET_ONLY:
1097 /* Dont store it skip*/
1098 break;
1099
1100 case TBTT_NEIGHBOR_AP_BSS_PARAM:
1101 /* Dont store it skip*/
1102 break;
1103
1104 case TBTT_NEIGHBOR_AP_S_SSID_BSS_PARAM:
1105 rnr->bss_params = data[5];
1106 fallthrough;
1107 case TBTT_NEIGHBOR_AP_SHORTSSID:
1108 rnr->channel_number = ap_info->channel_number;
1109 rnr->operating_class = ap_info->operting_class;
1110 qdf_mem_copy(&rnr->short_ssid, &data[1], SHORT_SSID_LEN);
1111 break;
1112
1113 case TBTT_NEIGHBOR_AP_BSSID_BSS_PARAM_20MHZ_PSD:
1114 rnr->psd_20mhz = data[8];
1115 fallthrough;
1116 case TBTT_NEIGHBOR_AP_BSSID_BSS_PARAM:
1117 rnr->bss_params = data[7];
1118 fallthrough;
1119 case TBTT_NEIGHBOR_AP_BSSID:
1120 rnr->channel_number = ap_info->channel_number;
1121 rnr->operating_class = ap_info->operting_class;
1122 qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE);
1123 break;
1124
1125 case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD_MLD_PARAM:
1126 util_scan_update_rnr_mld(rnr, data, tbtt_info_length);
1127 fallthrough;
1128 case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD:
1129 rnr->psd_20mhz = data[12];
1130 fallthrough;
1131 case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM:
1132 rnr->bss_params = data[11];
1133 fallthrough;
1134 case TBTT_NEIGHBOR_AP_BSSSID_S_SSID:
1135 rnr->channel_number = ap_info->channel_number;
1136 rnr->operating_class = ap_info->operting_class;
1137 qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE);
1138 qdf_mem_copy(&rnr->short_ssid, &data[7], SHORT_SSID_LEN);
1139 break;
1140
1141 default:
1142 scm_debug("Wrong fieldtype");
1143 }
1144
1145 return QDF_STATUS_SUCCESS;
1146 }
1147
1148 static QDF_STATUS
util_scan_parse_rnr_ie(struct scan_cache_entry * scan_entry,struct ie_header * ie)1149 util_scan_parse_rnr_ie(struct scan_cache_entry *scan_entry,
1150 struct ie_header *ie)
1151 {
1152 uint32_t rnr_ie_len;
1153 uint16_t tbtt_count, tbtt_length, i, fieldtype, idx;
1154 uint8_t *data;
1155 struct neighbor_ap_info_field *neighbor_ap_info;
1156
1157 rnr_ie_len = ie->ie_len;
1158 data = (uint8_t *)ie + sizeof(struct ie_header);
1159 idx = scan_entry->rnr.count;
1160
1161 while ((data + sizeof(struct neighbor_ap_info_field)) <=
1162 ((uint8_t *)ie + rnr_ie_len + 2)) {
1163 neighbor_ap_info = (struct neighbor_ap_info_field *)data;
1164 tbtt_count = neighbor_ap_info->tbtt_header.tbtt_info_count;
1165 tbtt_length = neighbor_ap_info->tbtt_header.tbtt_info_length;
1166 fieldtype = neighbor_ap_info->tbtt_header.tbbt_info_fieldtype;
1167 scm_debug("chan %d, opclass %d tbtt_cnt %d, tbtt_len %d, fieldtype %d",
1168 neighbor_ap_info->channel_number,
1169 neighbor_ap_info->operting_class,
1170 tbtt_count, tbtt_length, fieldtype);
1171 data += sizeof(struct neighbor_ap_info_field);
1172
1173 if (tbtt_count > TBTT_INFO_COUNT)
1174 break;
1175
1176 for (i = 0; i < (tbtt_count + 1) &&
1177 (data + tbtt_length) <=
1178 ((uint8_t *)ie + rnr_ie_len + 2); i++) {
1179 if ((i < MAX_RNR_BSS) && (idx < MAX_RNR_BSS))
1180 util_scan_update_rnr(
1181 &scan_entry->rnr.bss_info[idx++],
1182 neighbor_ap_info,
1183 data);
1184 data += tbtt_length;
1185 }
1186 }
1187
1188 scan_entry->rnr.count = idx;
1189
1190 return QDF_STATUS_SUCCESS;
1191 }
1192
1193 #ifdef WLAN_FEATURE_11BE_MLO
1194 static void
util_scan_parse_t2lm_ie(struct scan_cache_entry * scan_params,struct extn_ie_header * extn_ie)1195 util_scan_parse_t2lm_ie(struct scan_cache_entry *scan_params,
1196 struct extn_ie_header *extn_ie)
1197 {
1198 uint8_t t2lm_idx = 0;
1199
1200 if (extn_ie->ie_extn_id == WLAN_EXTN_ELEMID_T2LM)
1201 for (t2lm_idx = 0; t2lm_idx < WLAN_MAX_T2LM_IE; t2lm_idx++) {
1202 if (!scan_params->ie_list.t2lm[t2lm_idx]) {
1203 scan_params->ie_list.t2lm[t2lm_idx] =
1204 (uint8_t *)extn_ie;
1205 return;
1206 }
1207 }
1208 }
1209 #endif
1210
1211 #ifdef WLAN_FEATURE_11BE
1212 #ifdef WLAN_FEATURE_11BE_MLO
util_scan_parse_ml_ie(struct scan_cache_entry * scan_params,struct extn_ie_header * extn_ie)1213 static void util_scan_parse_ml_ie(struct scan_cache_entry *scan_params,
1214 struct extn_ie_header *extn_ie)
1215 {
1216 uint8_t *ml_ie;
1217 uint32_t ml_ie_len;
1218 enum wlan_ml_variant ml_variant;
1219 QDF_STATUS ret;
1220
1221 if (extn_ie->ie_extn_id != WLAN_EXTN_ELEMID_MULTI_LINK)
1222 return;
1223
1224 ml_ie = (uint8_t *)extn_ie;
1225 ml_ie_len = ml_ie[TAG_LEN_POS];
1226
1227 /* Adding the size of IE header to ML IE length */
1228 ml_ie_len += sizeof(struct ie_header);
1229 ret = util_get_mlie_variant(ml_ie, ml_ie_len, (int *)&ml_variant);
1230 if (ret) {
1231 scm_err("Unable to get ml variant");
1232 return;
1233 }
1234
1235 switch (ml_variant) {
1236 case WLAN_ML_VARIANT_BASIC:
1237 scan_params->ie_list.multi_link_bv = (uint8_t *)extn_ie;
1238 break;
1239 case WLAN_ML_VARIANT_RECONFIG:
1240 scan_params->ie_list.multi_link_rv = (uint8_t *)extn_ie;
1241 break;
1242 default:
1243 break;
1244 }
1245 }
1246 #else
util_scan_parse_ml_ie(struct scan_cache_entry * scan_params,struct extn_ie_header * extn_ie)1247 static void util_scan_parse_ml_ie(struct scan_cache_entry *scan_params,
1248 struct extn_ie_header *extn_ie)
1249 {
1250 }
1251 #endif
util_scan_parse_eht_ie(struct scan_cache_entry * scan_params,struct extn_ie_header * extn_ie)1252 static void util_scan_parse_eht_ie(struct scan_cache_entry *scan_params,
1253 struct extn_ie_header *extn_ie)
1254 {
1255 switch (extn_ie->ie_extn_id) {
1256 case WLAN_EXTN_ELEMID_EHTCAP:
1257 scan_params->ie_list.ehtcap = (uint8_t *)extn_ie;
1258 break;
1259 case WLAN_EXTN_ELEMID_EHTOP:
1260 scan_params->ie_list.ehtop = (uint8_t *)extn_ie;
1261 break;
1262 default:
1263 break;
1264 }
1265
1266 util_scan_parse_ml_ie(scan_params, extn_ie);
1267 util_scan_parse_t2lm_ie(scan_params, extn_ie);
1268 }
1269 #else
util_scan_parse_eht_ie(struct scan_cache_entry * scan_params,struct extn_ie_header * extn_ie)1270 static void util_scan_parse_eht_ie(struct scan_cache_entry *scan_params,
1271 struct extn_ie_header *extn_ie)
1272 {
1273 }
1274 #endif
1275
1276 static QDF_STATUS
util_scan_parse_extn_ie(struct scan_cache_entry * scan_params,struct ie_header * ie)1277 util_scan_parse_extn_ie(struct scan_cache_entry *scan_params,
1278 struct ie_header *ie)
1279 {
1280 struct extn_ie_header *extn_ie = (struct extn_ie_header *) ie;
1281
1282 switch (extn_ie->ie_extn_id) {
1283 case WLAN_EXTN_ELEMID_MAX_CHAN_SWITCH_TIME:
1284 if (extn_ie->ie_len != WLAN_MAX_CHAN_SWITCH_TIME_IE_LEN)
1285 return QDF_STATUS_E_INVAL;
1286 scan_params->ie_list.mcst = (uint8_t *)ie;
1287 break;
1288 case WLAN_EXTN_ELEMID_SRP:
1289 if (extn_ie->ie_len > WLAN_MAX_SRP_IE_LEN)
1290 return QDF_STATUS_E_INVAL;
1291 scan_params->ie_list.srp = (uint8_t *)ie;
1292 break;
1293 case WLAN_EXTN_ELEMID_HECAP:
1294 if ((extn_ie->ie_len < WLAN_MIN_HECAP_IE_LEN) ||
1295 (extn_ie->ie_len > WLAN_MAX_HECAP_IE_LEN))
1296 return QDF_STATUS_E_INVAL;
1297 scan_params->ie_list.hecap = (uint8_t *)ie;
1298 break;
1299 case WLAN_EXTN_ELEMID_HEOP:
1300 if (extn_ie->ie_len > WLAN_MAX_HEOP_IE_LEN)
1301 return QDF_STATUS_E_INVAL;
1302 scan_params->ie_list.heop = (uint8_t *)ie;
1303 break;
1304 case WLAN_EXTN_ELEMID_ESP:
1305 scan_params->ie_list.esp = (uint8_t *)ie;
1306 break;
1307 case WLAN_EXTN_ELEMID_MUEDCA:
1308 if (extn_ie->ie_len > WLAN_MAX_MUEDCA_IE_LEN)
1309 return QDF_STATUS_E_INVAL;
1310 scan_params->ie_list.muedca = (uint8_t *)ie;
1311 break;
1312 case WLAN_EXTN_ELEMID_HE_6G_CAP:
1313 if (extn_ie->ie_len > WLAN_MAX_HE_6G_CAP_IE_LEN)
1314 return QDF_STATUS_E_INVAL;
1315 scan_params->ie_list.hecap_6g = (uint8_t *)ie;
1316 break;
1317 default:
1318 break;
1319 }
1320 util_scan_parse_eht_ie(scan_params, extn_ie);
1321
1322 return QDF_STATUS_SUCCESS;
1323 }
1324
1325 static QDF_STATUS
util_scan_parse_vendor_ie(struct scan_cache_entry * scan_params,struct ie_header * ie)1326 util_scan_parse_vendor_ie(struct scan_cache_entry *scan_params,
1327 struct ie_header *ie)
1328 {
1329 if (!scan_params->ie_list.vendor)
1330 scan_params->ie_list.vendor = (uint8_t *)ie;
1331
1332 if (is_wpa_oui((uint8_t *)ie)) {
1333 scan_params->ie_list.wpa = (uint8_t *)ie;
1334 } else if (is_wps_oui((uint8_t *)ie)) {
1335 scan_params->ie_list.wps = (uint8_t *)ie;
1336 /* WCN IE should be a subset of WPS IE */
1337 if (is_wcn_oui((uint8_t *)ie))
1338 scan_params->ie_list.wcn = (uint8_t *)ie;
1339 } else if (is_wme_param((uint8_t *)ie)) {
1340 if (ie->ie_len > WLAN_VENDOR_WME_IE_LEN)
1341 return QDF_STATUS_E_INVAL;
1342
1343 scan_params->ie_list.wmeparam = (uint8_t *)ie;
1344 } else if (is_wme_info((uint8_t *)ie)) {
1345 scan_params->ie_list.wmeinfo = (uint8_t *)ie;
1346 } else if (is_atheros_oui((uint8_t *)ie)) {
1347 if (ie->ie_len > WLAN_VENDOR_ATHCAPS_IE_LEN)
1348 return QDF_STATUS_E_INVAL;
1349
1350 scan_params->ie_list.athcaps = (uint8_t *)ie;
1351 } else if (is_atheros_extcap_oui((uint8_t *)ie)) {
1352 if (ie->ie_len > WLAN_VENDOR_ATH_EXTCAP_IE_LEN)
1353 return QDF_STATUS_E_INVAL;
1354
1355 scan_params->ie_list.athextcaps = (uint8_t *)ie;
1356 } else if (is_sfa_oui((uint8_t *)ie)) {
1357 if (ie->ie_len > WLAN_VENDOR_SFA_IE_LEN)
1358 return QDF_STATUS_E_INVAL;
1359
1360 scan_params->ie_list.sfa = (uint8_t *)ie;
1361 } else if (is_p2p_oui((uint8_t *)ie)) {
1362 scan_params->ie_list.p2p = (uint8_t *)ie;
1363 } else if (is_qca_son_oui((uint8_t *)ie,
1364 QCA_OUI_WHC_AP_INFO_SUBTYPE)) {
1365
1366 scan_params->ie_list.sonadv = (uint8_t *)ie;
1367 } else if (is_ht_cap((uint8_t *)ie)) {
1368 /* we only care if there isn't already an HT IE (ANA) */
1369 if (!scan_params->ie_list.htcap) {
1370 if (ie->ie_len != (WLAN_VENDOR_HT_IE_OFFSET_LEN +
1371 sizeof(struct htcap_cmn_ie)))
1372 return QDF_STATUS_E_INVAL;
1373 scan_params->ie_list.htcap =
1374 (uint8_t *)&(((struct wlan_vendor_ie_htcap *)ie)->ie);
1375 }
1376 } else if (is_ht_info((uint8_t *)ie)) {
1377 /* we only care if there isn't already an HT IE (ANA) */
1378 if (!scan_params->ie_list.htinfo) {
1379 if (ie->ie_len != WLAN_VENDOR_HT_IE_OFFSET_LEN +
1380 sizeof(struct wlan_ie_htinfo_cmn))
1381 return QDF_STATUS_E_INVAL;
1382 scan_params->ie_list.htinfo =
1383 (uint8_t *)&(((struct wlan_vendor_ie_htinfo *)
1384 ie)->hi_ie);
1385 }
1386 } else if (is_interop_vht((uint8_t *)ie) &&
1387 !(scan_params->ie_list.vhtcap)) {
1388 uint8_t *vendor_ie = (uint8_t *)(ie);
1389
1390 if (ie->ie_len < ((WLAN_VENDOR_VHTCAP_IE_OFFSET +
1391 sizeof(struct wlan_ie_vhtcaps)) -
1392 sizeof(struct ie_header)))
1393 return QDF_STATUS_E_INVAL;
1394 vendor_ie = ((uint8_t *)(ie)) + WLAN_VENDOR_VHTCAP_IE_OFFSET;
1395 if (vendor_ie[1] != (sizeof(struct wlan_ie_vhtcaps)) -
1396 sizeof(struct ie_header))
1397 return QDF_STATUS_E_INVAL;
1398 /* location where Interop Vht Cap IE and VHT OP IE Present */
1399 scan_params->ie_list.vhtcap = (((uint8_t *)(ie)) +
1400 WLAN_VENDOR_VHTCAP_IE_OFFSET);
1401 if (ie->ie_len > ((WLAN_VENDOR_VHTCAP_IE_OFFSET +
1402 sizeof(struct wlan_ie_vhtcaps)) -
1403 sizeof(struct ie_header))) {
1404 if (ie->ie_len < ((WLAN_VENDOR_VHTOP_IE_OFFSET +
1405 sizeof(struct wlan_ie_vhtop)) -
1406 sizeof(struct ie_header)))
1407 return QDF_STATUS_E_INVAL;
1408 vendor_ie = ((uint8_t *)(ie)) +
1409 WLAN_VENDOR_VHTOP_IE_OFFSET;
1410 if (vendor_ie[1] != (sizeof(struct wlan_ie_vhtop) -
1411 sizeof(struct ie_header)))
1412 return QDF_STATUS_E_INVAL;
1413 scan_params->ie_list.vhtop = (((uint8_t *)(ie)) +
1414 WLAN_VENDOR_VHTOP_IE_OFFSET);
1415 }
1416 } else if (is_bwnss_oui((uint8_t *)ie)) {
1417 /*
1418 * Bandwidth-NSS map has sub-type & version.
1419 * hence copy data just after version byte
1420 */
1421 if (ie->ie_len > WLAN_BWNSS_MAP_OFFSET)
1422 scan_params->ie_list.bwnss_map = (((uint8_t *)ie) + 8);
1423 } else if (is_mbo_oce_oui((uint8_t *)ie)) {
1424 scan_params->ie_list.mbo_oce = (uint8_t *)ie;
1425 } else if (is_extender_oui((uint8_t *)ie)) {
1426 scan_params->ie_list.extender = (uint8_t *)ie;
1427 } else if (is_adaptive_11r_oui((uint8_t *)ie)) {
1428 if ((ie->ie_len < OUI_LENGTH) ||
1429 (ie->ie_len > MAX_ADAPTIVE_11R_IE_LEN))
1430 return QDF_STATUS_E_INVAL;
1431
1432 scan_params->ie_list.adaptive_11r = (uint8_t *)ie +
1433 sizeof(struct ie_header);
1434 } else if (is_sae_single_pmk_oui((uint8_t *)ie)) {
1435 if ((ie->ie_len < OUI_LENGTH) ||
1436 (ie->ie_len > MAX_SAE_SINGLE_PMK_IE_LEN)) {
1437 scm_debug("Invalid sae single pmk OUI");
1438 return QDF_STATUS_E_INVAL;
1439 }
1440 scan_params->ie_list.single_pmk = (uint8_t *)ie +
1441 sizeof(struct ie_header);
1442 } else if (is_qcn_oui((uint8_t *)ie)) {
1443 scan_params->ie_list.qcn = (uint8_t *)ie;
1444 }
1445
1446 return QDF_STATUS_SUCCESS;
1447 }
1448
1449 static QDF_STATUS
util_scan_populate_bcn_ie_list(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params,qdf_freq_t * chan_freq,uint8_t band_mask)1450 util_scan_populate_bcn_ie_list(struct wlan_objmgr_pdev *pdev,
1451 struct scan_cache_entry *scan_params,
1452 qdf_freq_t *chan_freq, uint8_t band_mask)
1453 {
1454 struct ie_header *ie, *sub_ie;
1455 uint32_t ie_len, sub_ie_len;
1456 QDF_STATUS status;
1457 uint8_t chan_idx;
1458 struct wlan_scan_obj *scan_obj;
1459 struct wlan_objmgr_psoc *psoc;
1460 uint8_t tpe_idx = 0;
1461
1462 psoc = wlan_pdev_get_psoc(pdev);
1463 if (!psoc) {
1464 scm_err("psoc is NULL");
1465 return QDF_STATUS_E_INVAL;
1466 }
1467
1468 scan_obj = wlan_psoc_get_scan_obj(psoc);
1469 if (!scan_obj) {
1470 scm_err("scan_obj is NULL");
1471 return QDF_STATUS_E_INVAL;
1472 }
1473
1474 ie_len = util_scan_entry_ie_len(scan_params);
1475 ie = (struct ie_header *)
1476 util_scan_entry_ie_data(scan_params);
1477
1478 while (ie_len >= sizeof(struct ie_header)) {
1479 ie_len -= sizeof(struct ie_header);
1480
1481 if (!ie->ie_len) {
1482 ie += 1;
1483 continue;
1484 }
1485
1486 if (ie_len < ie->ie_len) {
1487 if (scan_obj->allow_bss_with_incomplete_ie) {
1488 scm_debug(QDF_MAC_ADDR_FMT": Scan allowed with incomplete corrupted IE:%x, ie_len: %d, ie->ie_len: %d, stop processing further",
1489 QDF_MAC_ADDR_REF(scan_params->bssid.bytes),
1490 ie->ie_id, ie_len, ie->ie_len);
1491 break;
1492 }
1493 scm_debug(QDF_MAC_ADDR_FMT": Scan not allowed with incomplete corrupted IE:%x, ie_len: %d, ie->ie_len: %d, stop processing further",
1494 QDF_MAC_ADDR_REF(scan_params->bssid.bytes),
1495 ie->ie_id, ie_len, ie->ie_len);
1496 return QDF_STATUS_E_INVAL;
1497 }
1498
1499 switch (ie->ie_id) {
1500 case WLAN_ELEMID_SSID:
1501 if (ie->ie_len > (sizeof(struct ie_ssid) -
1502 sizeof(struct ie_header)))
1503 goto err;
1504 scan_params->ie_list.ssid = (uint8_t *)ie;
1505 break;
1506 case WLAN_ELEMID_RATES:
1507 if (ie->ie_len > WLAN_SUPPORTED_RATES_IE_MAX_LEN)
1508 goto err;
1509 scan_params->ie_list.rates = (uint8_t *)ie;
1510 break;
1511 case WLAN_ELEMID_DSPARMS:
1512 if (ie->ie_len != WLAN_DS_PARAM_IE_MAX_LEN)
1513 return QDF_STATUS_E_INVAL;
1514 scan_params->ie_list.ds_param = (uint8_t *)ie;
1515 chan_idx = ((struct ds_ie *)ie)->cur_chan;
1516 *chan_freq = wlan_reg_chan_band_to_freq(pdev, chan_idx,
1517 band_mask);
1518 /* Drop if invalid freq */
1519 if (scan_obj->drop_bcn_on_invalid_freq &&
1520 !wlan_reg_is_freq_enabled(pdev,
1521 *chan_freq,
1522 REG_CURRENT_PWR_MODE)) {
1523 scm_debug(QDF_MAC_ADDR_FMT": Drop as invalid chan %d in DS IE, freq %d, band_mask %d",
1524 QDF_MAC_ADDR_REF(
1525 scan_params->bssid.bytes),
1526 chan_idx, *chan_freq, band_mask);
1527 return QDF_STATUS_E_INVAL;
1528 }
1529 break;
1530 case WLAN_ELEMID_TIM:
1531 if (ie->ie_len < WLAN_TIM_IE_MIN_LENGTH)
1532 goto err;
1533 scan_params->ie_list.tim = (uint8_t *)ie;
1534 scan_params->dtim_period =
1535 ((struct wlan_tim_ie *)ie)->tim_period;
1536 break;
1537 case WLAN_ELEMID_COUNTRY:
1538 if (ie->ie_len < WLAN_COUNTRY_IE_MIN_LEN)
1539 goto err;
1540 scan_params->ie_list.country = (uint8_t *)ie;
1541 break;
1542 case WLAN_ELEMID_QBSS_LOAD:
1543 if (ie->ie_len != sizeof(struct qbss_load_ie) -
1544 sizeof(struct ie_header)) {
1545 /*
1546 * Expected QBSS IE length is 5Bytes; For some
1547 * old cisco AP, QBSS IE length is 4Bytes, which
1548 * doesn't match with latest spec, So ignore
1549 * QBSS IE in such case.
1550 */
1551 break;
1552 }
1553 scan_params->ie_list.qbssload = (uint8_t *)ie;
1554 break;
1555 case WLAN_ELEMID_CHANSWITCHANN:
1556 if (ie->ie_len != WLAN_CSA_IE_MAX_LEN)
1557 goto err;
1558 scan_params->ie_list.csa = (uint8_t *)ie;
1559 break;
1560 case WLAN_ELEMID_IBSSDFS:
1561 if (ie->ie_len < WLAN_IBSSDFS_IE_MIN_LEN)
1562 goto err;
1563 scan_params->ie_list.ibssdfs = (uint8_t *)ie;
1564 break;
1565 case WLAN_ELEMID_QUIET:
1566 if (ie->ie_len != WLAN_QUIET_IE_MAX_LEN)
1567 goto err;
1568 scan_params->ie_list.quiet = (uint8_t *)ie;
1569 break;
1570 case WLAN_ELEMID_ERP:
1571 if (ie->ie_len != (sizeof(struct erp_ie) -
1572 sizeof(struct ie_header)))
1573 goto err;
1574 scan_params->erp = ((struct erp_ie *)ie)->value;
1575 break;
1576 case WLAN_ELEMID_HTCAP_ANA:
1577 if (ie->ie_len == sizeof(struct htcap_cmn_ie)) {
1578 scan_params->ie_list.htcap =
1579 (uint8_t *)&(((struct htcap_ie *)ie)->ie);
1580 }
1581 break;
1582 case WLAN_ELEMID_RSN:
1583 /*
1584 * For security cert TC, RSNIE length can be 1 but if
1585 * beacon is dropped, old entry will remain in scan
1586 * cache and cause cert TC failure as connection with
1587 * old entry with valid RSN IE will pass.
1588 * So instead of dropping the frame, do not store the
1589 * RSN pointer so that old entry is overwritten.
1590 */
1591 if (ie->ie_len >= WLAN_RSN_IE_MIN_LEN)
1592 scan_params->ie_list.rsn = (uint8_t *)ie;
1593 break;
1594 case WLAN_ELEMID_XRATES:
1595 if (ie->ie_len > WLAN_EXT_SUPPORTED_RATES_IE_MAX_LEN)
1596 goto err;
1597 scan_params->ie_list.xrates = (uint8_t *)ie;
1598 break;
1599 case WLAN_ELEMID_EXTCHANSWITCHANN:
1600 if (ie->ie_len != WLAN_XCSA_IE_MAX_LEN)
1601 goto err;
1602 scan_params->ie_list.xcsa = (uint8_t *)ie;
1603 break;
1604 case WLAN_ELEMID_SECCHANOFFSET:
1605 if (ie->ie_len != WLAN_SECCHANOFF_IE_MAX_LEN)
1606 goto err;
1607 scan_params->ie_list.secchanoff = (uint8_t *)ie;
1608 break;
1609 case WLAN_ELEMID_HTINFO_ANA:
1610 if (ie->ie_len != sizeof(struct wlan_ie_htinfo_cmn))
1611 goto err;
1612 scan_params->ie_list.htinfo =
1613 (uint8_t *)&(((struct wlan_ie_htinfo *) ie)->hi_ie);
1614 chan_idx = ((struct wlan_ie_htinfo_cmn *)
1615 (scan_params->ie_list.htinfo))->hi_ctrlchannel;
1616 *chan_freq = wlan_reg_chan_band_to_freq(pdev, chan_idx,
1617 band_mask);
1618 /* Drop if invalid freq */
1619 if (scan_obj->drop_bcn_on_invalid_freq &&
1620 !wlan_reg_is_freq_enabled(pdev,
1621 *chan_freq,
1622 REG_CURRENT_PWR_MODE)) {
1623 scm_debug_rl(QDF_MAC_ADDR_FMT": Drop as invalid channel %d freq %d in HT_INFO IE",
1624 QDF_MAC_ADDR_REF(scan_params->bssid.bytes),
1625 chan_idx, *chan_freq);
1626 return QDF_STATUS_E_INVAL;
1627 }
1628 break;
1629 case WLAN_ELEMID_WAPI:
1630 if (ie->ie_len < WLAN_WAPI_IE_MIN_LEN)
1631 goto err;
1632 scan_params->ie_list.wapi = (uint8_t *)ie;
1633 break;
1634 case WLAN_ELEMID_XCAPS:
1635 if (ie->ie_len > WLAN_EXTCAP_IE_MAX_LEN)
1636 goto err;
1637 scan_params->ie_list.extcaps = (uint8_t *)ie;
1638 break;
1639 case WLAN_ELEMID_VHTCAP:
1640 if (ie->ie_len != (sizeof(struct wlan_ie_vhtcaps) -
1641 sizeof(struct ie_header)))
1642 goto err;
1643 scan_params->ie_list.vhtcap = (uint8_t *)ie;
1644 break;
1645 case WLAN_ELEMID_VHTOP:
1646 if (ie->ie_len != (sizeof(struct wlan_ie_vhtop) -
1647 sizeof(struct ie_header)))
1648 goto err;
1649 scan_params->ie_list.vhtop = (uint8_t *)ie;
1650 break;
1651 case WLAN_ELEMID_OP_MODE_NOTIFY:
1652 if (ie->ie_len != WLAN_OPMODE_IE_MAX_LEN)
1653 goto err;
1654 scan_params->ie_list.opmode = (uint8_t *)ie;
1655 break;
1656 case WLAN_ELEMID_MOBILITY_DOMAIN:
1657 if (ie->ie_len != WLAN_MOBILITY_DOMAIN_IE_MAX_LEN)
1658 goto err;
1659 scan_params->ie_list.mdie = (uint8_t *)ie;
1660 break;
1661 case WLAN_ELEMID_VENDOR:
1662 status = util_scan_parse_vendor_ie(scan_params,
1663 ie);
1664 if (QDF_IS_STATUS_ERROR(status))
1665 goto err_status;
1666 break;
1667 case WLAN_ELEMID_VHT_TX_PWR_ENVLP:
1668 if (ie->ie_len < WLAN_TPE_IE_MIN_LEN)
1669 goto err;
1670 if (tpe_idx >= WLAN_MAX_NUM_TPE_IE)
1671 goto err;
1672 scan_params->ie_list.tpe[tpe_idx++] = (uint8_t *)ie;
1673 break;
1674 case WLAN_ELEMID_CHAN_SWITCH_WRAP:
1675 scan_params->ie_list.cswrp = (uint8_t *)ie;
1676 /* Go to next sub IE */
1677 sub_ie = (struct ie_header *)
1678 (((uint8_t *)ie) + sizeof(struct ie_header));
1679 sub_ie_len = ie->ie_len;
1680 status =
1681 util_scan_parse_chan_switch_wrapper_ie(
1682 scan_params, sub_ie, sub_ie_len);
1683 if (QDF_IS_STATUS_ERROR(status)) {
1684 goto err_status;
1685 }
1686 break;
1687 case WLAN_ELEMID_FILS_INDICATION:
1688 if (ie->ie_len < WLAN_FILS_INDICATION_IE_MIN_LEN)
1689 goto err;
1690 scan_params->ie_list.fils_indication = (uint8_t *)ie;
1691 break;
1692 case WLAN_ELEMID_RSNXE:
1693 if (!ie->ie_len)
1694 goto err;
1695 scan_params->ie_list.rsnxe = (uint8_t *)ie;
1696 break;
1697 case WLAN_ELEMID_EXTN_ELEM:
1698 status = util_scan_parse_extn_ie(scan_params, ie);
1699 if (QDF_IS_STATUS_ERROR(status))
1700 goto err_status;
1701 break;
1702 case WLAN_ELEMID_REDUCED_NEIGHBOR_REPORT:
1703 if (ie->ie_len < WLAN_RNR_IE_MIN_LEN)
1704 goto err;
1705 scan_params->ie_list.rnrie = (uint8_t *)ie;
1706 status = util_scan_parse_rnr_ie(scan_params, ie);
1707 if (QDF_IS_STATUS_ERROR(status))
1708 goto err_status;
1709 break;
1710 default:
1711 break;
1712 }
1713
1714 /* Consume info element */
1715 ie_len -= ie->ie_len;
1716 /* Go to next IE */
1717 ie = (struct ie_header *)
1718 (((uint8_t *) ie) +
1719 sizeof(struct ie_header) +
1720 ie->ie_len);
1721 }
1722
1723 return QDF_STATUS_SUCCESS;
1724
1725 err:
1726 status = QDF_STATUS_E_INVAL;
1727 err_status:
1728 scm_debug(QDF_MAC_ADDR_FMT ": failed to parse IE - id: %d, len: %d",
1729 QDF_MAC_ADDR_REF(scan_params->bssid.bytes),
1730 ie->ie_id, ie->ie_len);
1731
1732 return status;
1733 }
1734
1735 /**
1736 * util_scan_update_esp_data: update ESP params from beacon/probe response
1737 * @esp_information: pointer to wlan_esp_information
1738 * @scan_entry: new received entry
1739 *
1740 * The Estimated Service Parameters element is
1741 * used by a AP to provide information to another STA which
1742 * can then use the information as input to an algorithm to
1743 * generate an estimate of throughput between the two STAs.
1744 * The ESP Information List field contains from 1 to 4 ESP
1745 * Information fields(each field 24 bits), each corresponding
1746 * to an access category for which estimated service parameters
1747 * information is provided.
1748 *
1749 * Return: None
1750 */
util_scan_update_esp_data(struct wlan_esp_ie * esp_information,struct scan_cache_entry * scan_entry)1751 static void util_scan_update_esp_data(struct wlan_esp_ie *esp_information,
1752 struct scan_cache_entry *scan_entry)
1753 {
1754
1755 uint8_t *data;
1756 int i = 0;
1757 uint64_t total_elements;
1758 struct wlan_esp_info *esp_info;
1759 struct wlan_esp_ie *esp_ie;
1760
1761 esp_ie = (struct wlan_esp_ie *)
1762 util_scan_entry_esp_info(scan_entry);
1763
1764 // Ignore ESP_ID_EXTN element
1765 total_elements = esp_ie->esp_len - 1;
1766 data = (uint8_t *)esp_ie + 3;
1767 do_div(total_elements, ESP_INFORMATION_LIST_LENGTH);
1768
1769 if (total_elements > MAX_ESP_INFORMATION_FIELD) {
1770 scm_err("No of Air time fractions are greater than supported");
1771 return;
1772 }
1773
1774 for (i = 0; i < total_elements &&
1775 data < ((uint8_t *)esp_ie + esp_ie->esp_len); i++) {
1776 esp_info = (struct wlan_esp_info *)data;
1777 if (esp_info->access_category == ESP_AC_BK) {
1778 qdf_mem_copy(&esp_information->esp_info_AC_BK,
1779 data, 3);
1780 data = data + ESP_INFORMATION_LIST_LENGTH;
1781 continue;
1782 }
1783 if (esp_info->access_category == ESP_AC_BE) {
1784 qdf_mem_copy(&esp_information->esp_info_AC_BE,
1785 data, 3);
1786 data = data + ESP_INFORMATION_LIST_LENGTH;
1787 continue;
1788 }
1789 if (esp_info->access_category == ESP_AC_VI) {
1790 qdf_mem_copy(&esp_information->esp_info_AC_VI,
1791 data, 3);
1792 data = data + ESP_INFORMATION_LIST_LENGTH;
1793 continue;
1794 }
1795 if (esp_info->access_category == ESP_AC_VO) {
1796 qdf_mem_copy(&esp_information->esp_info_AC_VO,
1797 data, 3);
1798 data = data + ESP_INFORMATION_LIST_LENGTH;
1799 break;
1800 }
1801 }
1802 }
1803
1804 /**
1805 * util_scan_scm_update_bss_with_esp_data: calculate estimated air time
1806 * fraction
1807 * @scan_entry: new received entry
1808 *
1809 * This function process all Access category ESP params and provide
1810 * best effort air time fraction.
1811 * If best effort is not available, it will choose VI, VO and BK in sequence
1812 *
1813 */
util_scan_scm_update_bss_with_esp_data(struct scan_cache_entry * scan_entry)1814 static void util_scan_scm_update_bss_with_esp_data(
1815 struct scan_cache_entry *scan_entry)
1816 {
1817 uint8_t air_time_fraction = 0;
1818 struct wlan_esp_ie esp_information;
1819
1820 if (!scan_entry->ie_list.esp)
1821 return;
1822
1823 util_scan_update_esp_data(&esp_information, scan_entry);
1824
1825 /*
1826 * If the ESP metric is transmitting multiple airtime fractions, then
1827 * follow the sequence AC_BE, AC_VI, AC_VO, AC_BK and pick whichever is
1828 * the first one available
1829 */
1830 if (esp_information.esp_info_AC_BE.access_category
1831 == ESP_AC_BE)
1832 air_time_fraction =
1833 esp_information.esp_info_AC_BE.
1834 estimated_air_fraction;
1835 else if (esp_information.esp_info_AC_VI.access_category
1836 == ESP_AC_VI)
1837 air_time_fraction =
1838 esp_information.esp_info_AC_VI.
1839 estimated_air_fraction;
1840 else if (esp_information.esp_info_AC_VO.access_category
1841 == ESP_AC_VO)
1842 air_time_fraction =
1843 esp_information.esp_info_AC_VO.
1844 estimated_air_fraction;
1845 else if (esp_information.esp_info_AC_BK.access_category
1846 == ESP_AC_BK)
1847 air_time_fraction =
1848 esp_information.esp_info_AC_BK.
1849 estimated_air_fraction;
1850 scan_entry->air_time_fraction = air_time_fraction;
1851 }
1852
1853 /**
1854 * util_scan_scm_calc_nss_supported_by_ap() - finds out nss from AP
1855 * @scan_params: new received entry
1856 *
1857 * Return: number of nss advertised by AP
1858 */
util_scan_scm_calc_nss_supported_by_ap(struct scan_cache_entry * scan_params)1859 static int util_scan_scm_calc_nss_supported_by_ap(
1860 struct scan_cache_entry *scan_params)
1861 {
1862 struct htcap_cmn_ie *htcap;
1863 struct wlan_ie_vhtcaps *vhtcaps;
1864 uint8_t *he_cap;
1865 uint8_t *end_ptr = NULL;
1866 uint16_t rx_mcs_map = 0;
1867 uint8_t *mcs_map_offset;
1868
1869 htcap = (struct htcap_cmn_ie *)
1870 util_scan_entry_htcap(scan_params);
1871 vhtcaps = (struct wlan_ie_vhtcaps *)
1872 util_scan_entry_vhtcap(scan_params);
1873 he_cap = util_scan_entry_hecap(scan_params);
1874
1875 if (he_cap) {
1876 /* Using rx mcs map related to 80MHz or lower as in some
1877 * cases higher mcs may support lesser NSS than that
1878 * of lowe mcs. Thus giving max NSS capability.
1879 */
1880 end_ptr = he_cap + he_cap[1] + sizeof(struct ie_header);
1881 mcs_map_offset = (he_cap + sizeof(struct extn_ie_header) +
1882 WLAN_HE_MACCAP_LEN + WLAN_HE_PHYCAP_LEN);
1883 if ((mcs_map_offset + WLAN_HE_MCS_MAP_LEN) <= end_ptr) {
1884 rx_mcs_map = *(uint16_t *)mcs_map_offset;
1885 } else {
1886 rx_mcs_map = WLAN_INVALID_RX_MCS_MAP;
1887 scm_debug("mcs_map_offset exceeds he cap len");
1888 }
1889 } else if (vhtcaps) {
1890 rx_mcs_map = vhtcaps->rx_mcs_map;
1891 }
1892
1893 if (he_cap || vhtcaps) {
1894 if ((rx_mcs_map & 0xC000) != 0xC000)
1895 return 8;
1896
1897 if ((rx_mcs_map & 0x3000) != 0x3000)
1898 return 7;
1899
1900 if ((rx_mcs_map & 0x0C00) != 0x0C00)
1901 return 6;
1902
1903 if ((rx_mcs_map & 0x0300) != 0x0300)
1904 return 5;
1905
1906 if ((rx_mcs_map & 0x00C0) != 0x00C0)
1907 return 4;
1908
1909 if ((rx_mcs_map & 0x0030) != 0x0030)
1910 return 3;
1911
1912 if ((rx_mcs_map & 0x000C) != 0x000C)
1913 return 2;
1914 } else if (htcap) {
1915 if (htcap->mcsset[3])
1916 return 4;
1917
1918 if (htcap->mcsset[2])
1919 return 3;
1920
1921 if (htcap->mcsset[1])
1922 return 2;
1923
1924 }
1925 return 1;
1926 }
1927
1928 #ifdef WLAN_DFS_CHAN_HIDDEN_SSID
1929 QDF_STATUS
util_scan_add_hidden_ssid(struct wlan_objmgr_pdev * pdev,qdf_nbuf_t bcnbuf)1930 util_scan_add_hidden_ssid(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t bcnbuf)
1931 {
1932 struct wlan_frame_hdr *hdr;
1933 struct wlan_bcn_frame *bcn;
1934 struct wlan_scan_obj *scan_obj;
1935 struct wlan_ssid *conf_ssid;
1936 struct ie_header *ie;
1937 uint32_t frame_len = qdf_nbuf_len(bcnbuf);
1938 uint16_t bcn_ie_offset, ssid_ie_start_offset, ssid_ie_end_offset;
1939 uint16_t tmplen, ie_length;
1940 uint8_t *pbeacon, *tmp;
1941 bool set_ssid_flag = false;
1942 struct ie_ssid ssid = {0};
1943 uint8_t pdev_id;
1944
1945 if (!pdev) {
1946 scm_warn("pdev: 0x%pK is NULL", pdev);
1947 return QDF_STATUS_E_NULL_VALUE;
1948 }
1949 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
1950 scan_obj = wlan_pdev_get_scan_obj(pdev);
1951 if (!scan_obj) {
1952 scm_warn("null scan_obj");
1953 return QDF_STATUS_E_NULL_VALUE;
1954 }
1955
1956 conf_ssid = &scan_obj->pdev_info[pdev_id].conf_ssid;
1957
1958 hdr = (struct wlan_frame_hdr *)qdf_nbuf_data(bcnbuf);
1959
1960 /* received bssid does not match configured bssid */
1961 if (qdf_mem_cmp(hdr->i_addr3, scan_obj->pdev_info[pdev_id].conf_bssid,
1962 QDF_MAC_ADDR_SIZE) ||
1963 conf_ssid->length == 0) {
1964 return QDF_STATUS_SUCCESS;
1965 }
1966
1967 bcn = (struct wlan_bcn_frame *)(qdf_nbuf_data(bcnbuf) + sizeof(*hdr));
1968 pbeacon = (uint8_t *)bcn;
1969
1970 ie = (struct ie_header *)(pbeacon +
1971 offsetof(struct wlan_bcn_frame, ie));
1972
1973 bcn_ie_offset = offsetof(struct wlan_bcn_frame, ie);
1974 ie_length = (uint16_t)(frame_len - sizeof(*hdr) -
1975 bcn_ie_offset);
1976
1977 while (ie_length >= sizeof(struct ie_header)) {
1978 ie_length -= sizeof(struct ie_header);
1979
1980 bcn_ie_offset += sizeof(struct ie_header);
1981
1982 if (ie_length < ie->ie_len) {
1983 scm_debug("Incomplete corrupted IE:%x", ie->ie_id);
1984 return QDF_STATUS_E_INVAL;
1985 }
1986 if (ie->ie_id == WLAN_ELEMID_SSID) {
1987 if (ie->ie_len > (sizeof(struct ie_ssid) -
1988 sizeof(struct ie_header))) {
1989 return QDF_STATUS_E_INVAL;
1990 }
1991 ssid.ssid_id = ie->ie_id;
1992 ssid.ssid_len = ie->ie_len;
1993
1994 if (ssid.ssid_len)
1995 qdf_mem_copy(ssid.ssid,
1996 ie + sizeof(struct ie_header),
1997 ssid.ssid_len);
1998
1999 if (util_scan_is_hidden_ssid(&ssid)) {
2000 set_ssid_flag = true;
2001 ssid_ie_start_offset = bcn_ie_offset -
2002 sizeof(struct ie_header);
2003 ssid_ie_end_offset = bcn_ie_offset +
2004 ie->ie_len;
2005 }
2006 }
2007 if (ie->ie_len == 0) {
2008 ie += 1; /* next IE */
2009 continue;
2010 }
2011 if (ie->ie_id == WLAN_ELEMID_VENDOR &&
2012 is_wps_oui((uint8_t *)ie)) {
2013 set_ssid_flag = false;
2014 break;
2015 }
2016 /* Consume info element */
2017 ie_length -= ie->ie_len;
2018 /* Go to next IE */
2019 ie = (struct ie_header *)(((uint8_t *)ie) +
2020 sizeof(struct ie_header) +
2021 ie->ie_len);
2022 }
2023
2024 if (set_ssid_flag) {
2025 /* Hidden SSID if the Length is 0 */
2026 if (!ssid.ssid_len) {
2027 /* increase the taillength by length of ssid */
2028 if (qdf_nbuf_put_tail(bcnbuf,
2029 conf_ssid->length) == NULL) {
2030 scm_debug("No enough tailroom");
2031 return QDF_STATUS_E_NOMEM;
2032 }
2033 /*
2034 * "qdf_nbuf_put_tail" might change the data pointer of
2035 * the skb. Therefore use the new data area.
2036 */
2037 pbeacon = (qdf_nbuf_data(bcnbuf) + sizeof(*hdr));
2038 /* length of the buffer to be copied */
2039 tmplen = frame_len -
2040 sizeof(*hdr) - ssid_ie_end_offset;
2041 /*
2042 * tmp memory to copy the beacon info
2043 * after ssid ie.
2044 */
2045 tmp = qdf_mem_malloc(tmplen * sizeof(u_int8_t));
2046 if (!tmp)
2047 return QDF_STATUS_E_NOMEM;
2048
2049 /* Copy beacon data after ssid ie to tmp */
2050 qdf_nbuf_copy_bits(bcnbuf, (sizeof(*hdr) +
2051 ssid_ie_end_offset), tmplen, tmp);
2052 /* Add ssid length */
2053 *(pbeacon + (ssid_ie_start_offset + 1))
2054 = conf_ssid->length;
2055 /* Insert the SSID string */
2056 qdf_mem_copy((pbeacon + ssid_ie_end_offset),
2057 conf_ssid->ssid, conf_ssid->length);
2058 /* Copy rest of the beacon data */
2059 qdf_mem_copy((pbeacon + ssid_ie_end_offset +
2060 conf_ssid->length), tmp, tmplen);
2061 qdf_mem_free(tmp);
2062
2063 /* Hidden ssid with all 0's */
2064 } else if (ssid.ssid_len == conf_ssid->length) {
2065 /* Insert the SSID string */
2066 qdf_mem_copy((pbeacon + ssid_ie_start_offset +
2067 sizeof(struct ie_header)),
2068 conf_ssid->ssid, conf_ssid->length);
2069 } else {
2070 scm_debug("mismatch in hidden ssid length");
2071 return QDF_STATUS_E_INVAL;
2072 }
2073 }
2074 return QDF_STATUS_SUCCESS;
2075 }
2076 #endif /* WLAN_DFS_CHAN_HIDDEN_SSID */
2077
2078 #ifdef WLAN_ADAPTIVE_11R
2079 /**
2080 * scm_fill_adaptive_11r_cap() - Check if the AP supports adaptive 11r
2081 * @scan_entry: Pointer to the scan entry
2082 *
2083 * Return: true if adaptive 11r is advertised else false
2084 */
scm_fill_adaptive_11r_cap(struct scan_cache_entry * scan_entry)2085 static void scm_fill_adaptive_11r_cap(struct scan_cache_entry *scan_entry)
2086 {
2087 uint8_t *ie;
2088 uint8_t data;
2089 bool adaptive_11r;
2090
2091 ie = util_scan_entry_adaptive_11r(scan_entry);
2092 if (!ie)
2093 return;
2094
2095 data = *(ie + OUI_LENGTH);
2096 adaptive_11r = (data & 0x1) ? true : false;
2097
2098 scan_entry->adaptive_11r_ap = adaptive_11r;
2099 }
2100 #else
scm_fill_adaptive_11r_cap(struct scan_cache_entry * scan_entry)2101 static void scm_fill_adaptive_11r_cap(struct scan_cache_entry *scan_entry)
2102 {
2103 scan_entry->adaptive_11r_ap = false;
2104 }
2105 #endif
2106
util_scan_set_security(struct scan_cache_entry * scan_params)2107 static void util_scan_set_security(struct scan_cache_entry *scan_params)
2108 {
2109 if (util_scan_entry_wpa(scan_params))
2110 scan_params->security_type |= SCAN_SECURITY_TYPE_WPA;
2111
2112 if (util_scan_entry_rsn(scan_params))
2113 scan_params->security_type |= SCAN_SECURITY_TYPE_RSN;
2114 if (util_scan_entry_wapi(scan_params))
2115 scan_params->security_type |= SCAN_SECURITY_TYPE_WAPI;
2116
2117 if (!scan_params->security_type &&
2118 scan_params->cap_info.wlan_caps.privacy)
2119 scan_params->security_type |= SCAN_SECURITY_TYPE_WEP;
2120 }
2121
2122 #ifdef WLAN_FEATURE_11BE_MLO
2123 /*
2124 * Multi link IE field offsets
2125 * ------------------------------------------------------------------------
2126 * | EID(1) | Len (1) | EID_EXT (1) | ML_CONTROL (2) | CMN_INFO (var) | ... |
2127 * ------------------------------------------------------------------------
2128 */
2129 #define ML_CONTROL_OFFSET 3
2130 #define ML_CMN_INFO_OFFSET ML_CONTROL_OFFSET + 2
2131
2132 #define CMN_INFO_LINK_ID_PRESENT_BIT BIT(4)
2133 #define LINK_INFO_MAC_ADDR_PRESENT_BIT BIT(5)
2134
2135 /* This function is implemented as per IEEE802.11be D1.0, there is no difference
2136 * in presence bitmap for beacon, probe response and probe request frames.
2137 * This code is to be revisited for future drafts if the presence bitmap values
2138 * changes for the beacon, probe response and probe request frames.
2139 */
util_get_link_info_offset(uint8_t * ml_ie,bool * is_ml_ie_valid)2140 static uint8_t util_get_link_info_offset(uint8_t *ml_ie, bool *is_ml_ie_valid)
2141 {
2142 qdf_size_t ml_ie_len = 0;
2143 qdf_size_t parsed_ie_len = 0;
2144 struct wlan_ie_multilink *mlie_fixed;
2145 uint16_t mlcontrol;
2146 uint16_t presencebm;
2147 qdf_size_t actual_len;
2148
2149 if (!ml_ie) {
2150 scm_err("ml_ie is null");
2151 return 0;
2152 }
2153
2154 if (!is_ml_ie_valid) {
2155 scm_err_rl("is_ml_ie_valid is null");
2156 return 0;
2157 }
2158
2159 ml_ie_len = ml_ie[TAG_LEN_POS];
2160 if (!ml_ie_len) {
2161 scm_err("ml_ie_len is zero");
2162 return 0;
2163 }
2164
2165 if (ml_ie_len < sizeof(struct wlan_ie_multilink)) {
2166 scm_err_rl("Length %zu octets is smaller than required for the fixed portion of Multi-Link element (%zu octets)",
2167 ml_ie_len, sizeof(struct wlan_ie_multilink));
2168 return 0;
2169 }
2170
2171 mlie_fixed = (struct wlan_ie_multilink *)ml_ie;
2172 mlcontrol = le16toh(mlie_fixed->mlcontrol);
2173 presencebm = QDF_GET_BITS(mlcontrol, WLAN_ML_CTRL_PBM_IDX,
2174 WLAN_ML_CTRL_PBM_BITS);
2175
2176 parsed_ie_len += sizeof(*mlie_fixed);
2177
2178 parsed_ie_len += WLAN_ML_BV_CINFO_LENGTH_SIZE;
2179 parsed_ie_len += QDF_MAC_ADDR_SIZE;
2180
2181 /* Check if Link ID info is present */
2182 if (presencebm & WLAN_ML_BV_CTRL_PBM_LINKIDINFO_P)
2183 parsed_ie_len += WLAN_ML_BV_CINFO_LINKIDINFO_SIZE;
2184
2185 /* Check if BSS parameter change count is present */
2186 if (presencebm & WLAN_ML_BV_CTRL_PBM_BSSPARAMCHANGECNT_P)
2187 parsed_ie_len += WLAN_ML_BSSPARAMCHNGCNT_SIZE;
2188
2189 /* Check if Medium Sync Delay Info is present */
2190 if (presencebm & WLAN_ML_BV_CTRL_PBM_MEDIUMSYNCDELAYINFO_P)
2191 parsed_ie_len += WLAN_ML_BV_CINFO_MEDMSYNCDELAYINFO_SIZE;
2192
2193 /* Check if EML cap is present */
2194 if (presencebm & WLAN_ML_BV_CTRL_PBM_EMLCAP_P)
2195 parsed_ie_len += WLAN_ML_BV_CINFO_EMLCAP_SIZE;
2196
2197 /* Check if MLD cap and op is present */
2198 if (presencebm & WLAN_ML_BV_CTRL_PBM_MLDCAPANDOP_P)
2199 parsed_ie_len += WLAN_ML_BV_CINFO_MLDCAPANDOP_SIZE;
2200
2201 /* Check if MLD ID is present */
2202 if (presencebm & WLAN_ML_BV_CTRL_PBM_MLDID_P)
2203 parsed_ie_len += WLAN_ML_BV_CINFO_MLDID_SIZE;
2204
2205 /* Check if Extended MLD Cap and Op is present */
2206 if (presencebm & WLAN_ML_BV_CTRL_PBM_EXT_MLDCAPANDOP_P)
2207 parsed_ie_len += WLAN_ML_BV_CINFO_EXT_MLDCAPANDOP_SIZE;
2208
2209 /* Offset calculation starts from the beginning of the ML IE (including
2210 * EID) hence, adding the size of IE header to ML IE length.
2211 */
2212 actual_len = ml_ie_len + sizeof(struct ie_header);
2213 if (parsed_ie_len <= actual_len) {
2214 *is_ml_ie_valid = true;
2215 } else {
2216 *is_ml_ie_valid = false;
2217 scm_err("Invalid ML IE, expect min len: %zu, actual len: %zu",
2218 parsed_ie_len, actual_len);
2219 }
2220 if (parsed_ie_len < actual_len)
2221 return parsed_ie_len;
2222
2223 return 0;
2224 }
2225
2226 static void
util_get_ml_bv_partner_link_info(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_entry)2227 util_get_ml_bv_partner_link_info(struct wlan_objmgr_pdev *pdev,
2228 struct scan_cache_entry *scan_entry)
2229 {
2230 uint8_t *ml_ie = scan_entry->ie_list.multi_link_bv;
2231 uint8_t *end_ptr = NULL;
2232 bool is_ml_ie_valid;
2233 uint8_t offset = util_get_link_info_offset(ml_ie, &is_ml_ie_valid);
2234 uint16_t sta_ctrl;
2235 uint8_t *stactrl_offset = NULL, *ielist_offset;
2236 uint8_t perstaprof_len = 0, perstaprof_stainfo_len = 0, ielist_len = 0;
2237 struct partner_link_info *link_info = NULL;
2238 uint8_t eid = 0;
2239 uint8_t link_idx = 0;
2240 uint8_t rnr_idx = 0;
2241 struct rnr_bss_info *rnr = NULL;
2242 qdf_size_t ml_ie_len = ml_ie[TAG_LEN_POS] + sizeof(struct ie_header);
2243
2244 /* Update partner info from RNR IE */
2245 while ((rnr_idx < MAX_RNR_BSS) && (rnr_idx < scan_entry->rnr.count)) {
2246 if (link_idx >= (MLD_MAX_LINKS - 1))
2247 break;
2248 rnr = &scan_entry->rnr.bss_info[rnr_idx];
2249 if (rnr->mld_info_valid && !rnr->mld_info.mld_id) {
2250 link_info = &scan_entry->ml_info.link_info[link_idx];
2251 qdf_mem_copy(&link_info->link_addr,
2252 &rnr->bssid, QDF_MAC_ADDR_SIZE);
2253
2254 link_info->link_id = rnr->mld_info.link_id;
2255 link_info->freq =
2256 wlan_reg_chan_opclass_to_freq(rnr->channel_number,
2257 rnr->operating_class,
2258 true);
2259
2260 if (!link_info->freq)
2261 scm_debug_rl("freq 0 rnr channel %u op_class %u " QDF_MAC_ADDR_FMT,
2262 rnr->channel_number,
2263 rnr->operating_class,
2264 QDF_MAC_ADDR_REF(rnr->bssid.bytes));
2265 link_info->op_class = rnr->operating_class;
2266 link_idx++;
2267 }
2268 rnr_idx++;
2269 }
2270
2271 scan_entry->ml_info.num_links = link_idx;
2272 if (!offset ||
2273 (offset + sizeof(struct wlan_ml_bv_linfo_perstaprof) >= ml_ie_len)) {
2274 scm_debug_rl("incorrect offset value %d", offset);
2275 return;
2276 }
2277
2278 /* TODO: loop through all the STA info fields */
2279
2280 /*
2281 * Per-STA Profile subelement format of the Basic Multi-Link element
2282 *
2283 * |---------------|--------|-------------|----------|-------------|
2284 * | Subelement ID | Length | STA control | STA info | STA profile |
2285 * |---------------|--------|-------------|----------|-------------|
2286 * Octets: 1 1 2 variable variable
2287 */
2288
2289 /* Sub element ID 0 represents Per-STA Profile */
2290 if (ml_ie[offset] == 0) {
2291 perstaprof_len = ml_ie[offset + 1];
2292 stactrl_offset = &ml_ie[offset + 2];
2293 end_ptr = &ml_ie[offset] + perstaprof_len + 2;
2294
2295 if (!(end_ptr <= (ml_ie + ml_ie_len))) {
2296 if (ml_ie[TAG_LEN_POS] >= 255)
2297 scm_debug_rl("Possible fragmentation in ml_ie for tag_len %d. Ignore the processing",
2298 ml_ie[TAG_LEN_POS]);
2299 else
2300 scm_debug_rl("perstaprof exceeds ML IE boundary for tag_len %d. Ignore the processing",
2301 ml_ie[TAG_LEN_POS]);
2302 return;
2303 }
2304
2305 /* Skip sub element ID and length fields */
2306 offset += 2;
2307
2308 sta_ctrl = *(uint16_t *)(ml_ie + offset);
2309
2310 /* Skip STA control field */
2311 offset += 2;
2312
2313 /*
2314 * offset points to the beginning of the STA Info field which
2315 * indicates the number of octets in the STA Info field,
2316 * including one octet for the STA Info Length subfield.
2317 */
2318 perstaprof_stainfo_len = ml_ie[offset];
2319
2320 /* Skip STA Info Length field */
2321 offset += perstaprof_stainfo_len;
2322 if (offset >= ml_ie_len) {
2323 scm_err_rl("incorrect offset value %d", offset);
2324 return;
2325 }
2326
2327 /*
2328 * To point to the ie_list offset move past the STA Info
2329 * field.
2330 */
2331 ielist_offset = &ml_ie[offset];
2332
2333 /*
2334 * Ensure that the STA Control Field + STA Info Field
2335 * is smaller than the per-STA profile when incrementing
2336 * the pointer to avoid underflow during subtraction.
2337 */
2338 if ((perstaprof_stainfo_len +
2339 WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_SIZE) <
2340 perstaprof_len) {
2341 if (!(ielist_offset <= end_ptr))
2342 ielist_len = 0;
2343 else
2344 ielist_len = perstaprof_len -
2345 (WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_SIZE +
2346 perstaprof_stainfo_len);
2347 } else {
2348 scm_debug_rl("No STA profile IE list found for perstaprof_stainfo_len %d perstaprof_len %d",
2349 perstaprof_stainfo_len, perstaprof_len);
2350 ielist_len = 0;
2351 }
2352
2353 link_info = NULL;
2354 for (link_idx = 0; link_idx < scan_entry->ml_info.num_links;
2355 link_idx++) {
2356 if (scan_entry->ml_info.link_info[link_idx].link_id ==
2357 (sta_ctrl & 0xF)) {
2358 link_info = &scan_entry->ml_info.link_info[link_idx];
2359 }
2360 }
2361
2362 /* Get the pointers to CSA, ECSA, Max Channel Switch Time IE. */
2363 if (link_info) {
2364 link_info->csa_ie = wlan_get_ie_ptr_from_eid
2365 (WLAN_ELEMID_CHANSWITCHANN, ielist_offset,
2366 ielist_len);
2367
2368 link_info->ecsa_ie = wlan_get_ie_ptr_from_eid
2369 (WLAN_ELEMID_EXTCHANSWITCHANN, ielist_offset,
2370 ielist_len);
2371
2372 eid = WLAN_EXTN_ELEMID_MAX_CHAN_SWITCH_TIME;
2373 link_info->max_cst_ie = wlan_get_ext_ie_ptr_from_ext_id
2374 (&eid, 1, ielist_offset, ielist_len);
2375 }
2376 }
2377 }
2378
util_scan_update_ml_info(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_entry)2379 static void util_scan_update_ml_info(struct wlan_objmgr_pdev *pdev,
2380 struct scan_cache_entry *scan_entry)
2381 {
2382 uint8_t *ml_ie = scan_entry->ie_list.multi_link_bv;
2383 uint16_t multi_link_ctrl;
2384 uint8_t offset;
2385 uint8_t mlie_min_len;
2386 bool is_ml_ie_valid = true;
2387 uint8_t *end_ptr = NULL;
2388
2389 if (!scan_entry->ie_list.ehtcap && scan_entry->ie_list.multi_link_bv) {
2390 scan_entry->ie_list.multi_link_bv = NULL;
2391 return;
2392 }
2393 if (!scan_entry->ie_list.multi_link_bv)
2394 return;
2395
2396 mlie_min_len = util_get_link_info_offset(ml_ie, &is_ml_ie_valid);
2397 if (!is_ml_ie_valid) {
2398 scan_entry->ie_list.multi_link_bv = NULL;
2399 return;
2400 }
2401
2402 end_ptr = ml_ie + ml_ie[TAG_LEN_POS] + sizeof(struct ie_header);
2403
2404 multi_link_ctrl = *(uint16_t *)(ml_ie + ML_CONTROL_OFFSET);
2405
2406 /* TODO: update ml_info based on ML IE */
2407
2408 offset = ML_CMN_INFO_OFFSET;
2409
2410 /* Increment the offset to account for the Common Info Length */
2411 offset += WLAN_ML_BV_CINFO_LENGTH_SIZE;
2412
2413 if ((ml_ie + offset + QDF_MAC_ADDR_SIZE) <= end_ptr) {
2414 qdf_mem_copy(&scan_entry->ml_info.mld_mac_addr,
2415 ml_ie + offset, QDF_MAC_ADDR_SIZE);
2416 offset += QDF_MAC_ADDR_SIZE;
2417 }
2418
2419 /* TODO: Decode it from ML IE */
2420 scan_entry->ml_info.num_links = 0;
2421
2422 /**
2423 * Copy Link ID & MAC address of the scan cache entry as first entry
2424 * in the partner info list
2425 */
2426 if (multi_link_ctrl & CMN_INFO_LINK_ID_PRESENT_BIT) {
2427 if (&ml_ie[offset] < end_ptr)
2428 scan_entry->ml_info.self_link_id = ml_ie[offset] & 0x0F;
2429 }
2430
2431 util_get_ml_bv_partner_link_info(pdev, scan_entry);
2432 }
2433 #else
util_scan_update_ml_info(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_entry)2434 static void util_scan_update_ml_info(struct wlan_objmgr_pdev *pdev,
2435 struct scan_cache_entry *scan_entry)
2436 {
2437 }
2438 #endif
2439
2440 static QDF_STATUS
util_scan_gen_scan_entry(struct wlan_objmgr_pdev * pdev,uint8_t * frame,qdf_size_t frame_len,uint32_t frm_subtype,struct mgmt_rx_event_params * rx_param,struct scan_mbssid_info * mbssid_info,qdf_list_t * scan_list)2441 util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev,
2442 uint8_t *frame, qdf_size_t frame_len,
2443 uint32_t frm_subtype,
2444 struct mgmt_rx_event_params *rx_param,
2445 struct scan_mbssid_info *mbssid_info,
2446 qdf_list_t *scan_list)
2447 {
2448 struct wlan_frame_hdr *hdr;
2449 struct wlan_bcn_frame *bcn;
2450 QDF_STATUS status = QDF_STATUS_SUCCESS;
2451 struct ie_ssid *ssid;
2452 struct scan_cache_entry *scan_entry;
2453 struct qbss_load_ie *qbss_load;
2454 struct scan_cache_node *scan_node;
2455 uint8_t i;
2456 qdf_freq_t chan_freq = 0;
2457 bool is_6g_dup_bcon = false;
2458 uint8_t band_mask;
2459 qdf_freq_t recv_freq = 0;
2460
2461 scan_entry = qdf_mem_malloc_atomic(sizeof(*scan_entry));
2462 if (!scan_entry) {
2463 scm_err("failed to allocate memory for scan_entry");
2464 return QDF_STATUS_E_NOMEM;
2465 }
2466
2467 scan_entry->raw_frame.ptr =
2468 qdf_mem_malloc_atomic(frame_len);
2469 if (!scan_entry->raw_frame.ptr) {
2470 scm_err("failed to allocate memory for frame");
2471 qdf_mem_free(scan_entry);
2472 return QDF_STATUS_E_NOMEM;
2473 }
2474
2475 bcn = (struct wlan_bcn_frame *)
2476 (frame + sizeof(*hdr));
2477 hdr = (struct wlan_frame_hdr *)frame;
2478
2479 /* update timestamp in nanoseconds needed by kernel layers */
2480 scan_entry->boottime_ns = qdf_get_bootbased_boottime_ns();
2481
2482 scan_entry->frm_subtype = frm_subtype;
2483 qdf_mem_copy(scan_entry->bssid.bytes,
2484 hdr->i_addr3, QDF_MAC_ADDR_SIZE);
2485 /* Scr addr */
2486 qdf_mem_copy(scan_entry->mac_addr.bytes,
2487 hdr->i_addr2, QDF_MAC_ADDR_SIZE);
2488 scan_entry->seq_num =
2489 (le16toh(*(uint16_t *)hdr->i_seq) >> WLAN_SEQ_SEQ_SHIFT);
2490
2491 scan_entry->snr = rx_param->snr;
2492 scan_entry->avg_snr = WLAN_SNR_IN(scan_entry->snr);
2493 scan_entry->rssi_raw = rx_param->rssi;
2494 scan_entry->avg_rssi = WLAN_RSSI_IN(scan_entry->rssi_raw);
2495 scan_entry->tsf_delta = rx_param->tsf_delta;
2496 scan_entry->pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
2497
2498 recv_freq = rx_param->chan_freq;
2499 /* Copy per chain rssi to scan entry */
2500 qdf_mem_copy(scan_entry->per_chain_rssi, rx_param->rssi_ctl,
2501 WLAN_MGMT_TXRX_HOST_MAX_ANTENNA);
2502 band_mask = BIT(wlan_reg_freq_to_band(recv_freq));
2503
2504 if (!wlan_psoc_nif_fw_ext_cap_get(wlan_pdev_get_psoc(pdev),
2505 WLAN_SOC_CEXT_HW_DB2DBM)) {
2506 for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++) {
2507 if (scan_entry->per_chain_rssi[i] !=
2508 WLAN_INVALID_PER_CHAIN_SNR)
2509 scan_entry->per_chain_rssi[i] +=
2510 WLAN_NOISE_FLOOR_DBM_DEFAULT;
2511 else
2512 scan_entry->per_chain_rssi[i] =
2513 WLAN_INVALID_PER_CHAIN_RSSI;
2514 }
2515 }
2516
2517 /* store jiffies */
2518 scan_entry->rrm_parent_tsf = (uint32_t)qdf_system_ticks();
2519
2520 scan_entry->bcn_int = le16toh(bcn->beacon_interval);
2521
2522 /*
2523 * In case if the beacon doesn't have
2524 * valid beacon interval falback to def
2525 */
2526 if (!scan_entry->bcn_int)
2527 scan_entry->bcn_int = 100;
2528 scan_entry->cap_info.value = le16toh(bcn->capability.value);
2529 qdf_mem_copy(scan_entry->tsf_info.data,
2530 bcn->timestamp, 8);
2531 scan_entry->erp = ERP_NON_ERP_PRESENT;
2532
2533 scan_entry->scan_entry_time =
2534 qdf_mc_timer_get_system_time();
2535
2536 scan_entry->raw_frame.len = frame_len;
2537 qdf_mem_copy(scan_entry->raw_frame.ptr,
2538 frame, frame_len);
2539 status = util_scan_populate_bcn_ie_list(pdev, scan_entry, &chan_freq,
2540 band_mask);
2541 if (QDF_IS_STATUS_ERROR(status)) {
2542 qdf_mem_free(scan_entry->raw_frame.ptr);
2543 qdf_mem_free(scan_entry);
2544 return QDF_STATUS_E_FAILURE;
2545 }
2546
2547 ssid = (struct ie_ssid *)
2548 scan_entry->ie_list.ssid;
2549
2550 if (ssid && (ssid->ssid_len > WLAN_SSID_MAX_LEN)) {
2551 qdf_mem_free(scan_entry->raw_frame.ptr);
2552 qdf_mem_free(scan_entry);
2553 return QDF_STATUS_E_FAILURE;
2554 }
2555
2556 if (scan_entry->ie_list.p2p)
2557 scan_entry->is_p2p = true;
2558
2559 if (!chan_freq && util_scan_entry_hecap(scan_entry)) {
2560 status = util_scan_get_chan_from_he_6g_params(pdev, scan_entry,
2561 &chan_freq,
2562 &is_6g_dup_bcon,
2563 band_mask,
2564 recv_freq);
2565 if (QDF_IS_STATUS_ERROR(status)) {
2566 qdf_mem_free(scan_entry->raw_frame.ptr);
2567 qdf_mem_free(scan_entry);
2568 return QDF_STATUS_E_FAILURE;
2569 }
2570 }
2571
2572 if (chan_freq)
2573 scan_entry->channel.chan_freq = chan_freq;
2574
2575 /* If no channel info is present in beacon use meta channel */
2576 if (!scan_entry->channel.chan_freq) {
2577 scan_entry->channel.chan_freq = recv_freq;
2578 } else if (recv_freq !=
2579 scan_entry->channel.chan_freq) {
2580 if (!wlan_reg_is_49ghz_freq(scan_entry->channel.chan_freq) &&
2581 !is_6g_dup_bcon)
2582 scan_entry->channel_mismatch = true;
2583 }
2584
2585 if (util_scan_is_hidden_ssid(ssid)) {
2586 scan_entry->ie_list.ssid = NULL;
2587 scan_entry->is_hidden_ssid = true;
2588 } else {
2589 qdf_mem_copy(scan_entry->ssid.ssid,
2590 ssid->ssid, ssid->ssid_len);
2591 scan_entry->ssid.length = ssid->ssid_len;
2592 scan_entry->hidden_ssid_timestamp =
2593 scan_entry->scan_entry_time;
2594 }
2595 qdf_mem_copy(&scan_entry->mbssid_info, mbssid_info,
2596 sizeof(scan_entry->mbssid_info));
2597
2598 scan_entry->phy_mode = util_scan_get_phymode(pdev, scan_entry);
2599
2600 scan_entry->nss = util_scan_scm_calc_nss_supported_by_ap(scan_entry);
2601 scm_fill_adaptive_11r_cap(scan_entry);
2602 util_scan_set_security(scan_entry);
2603
2604 util_scan_scm_update_bss_with_esp_data(scan_entry);
2605 qbss_load = (struct qbss_load_ie *)
2606 util_scan_entry_qbssload(scan_entry);
2607 if (qbss_load)
2608 scan_entry->qbss_chan_load = qbss_load->qbss_chan_load;
2609
2610 scan_node = qdf_mem_malloc_atomic(sizeof(*scan_node));
2611 if (!scan_node) {
2612 qdf_mem_free(scan_entry->raw_frame.ptr);
2613 qdf_mem_free(scan_entry);
2614 scm_err("failed to allocate memory for scan_node");
2615 return QDF_STATUS_E_FAILURE;
2616 }
2617
2618 util_scan_update_ml_info(pdev, scan_entry);
2619
2620 scan_node->entry = scan_entry;
2621 qdf_list_insert_front(scan_list, &scan_node->node);
2622
2623 return status;
2624 }
2625
2626 #ifdef WLAN_FEATURE_MBSSID
2627 /*
2628 * util_is_noninh_ie() - find the noninhertance information element
2629 * in the received frame's IE list, so that we can stop inheriting that IE
2630 * in the caller function.
2631 *
2632 * @elem_id: Element ID in the received frame's IE, which is being processed.
2633 * @non_inh_list: pointer to the non inherited list of element IDs or
2634 * list of extension element IDs.
2635 * @len: Length of non inheritance IE list
2636 *
2637 * Return: False if the element ID is not found or else return true
2638 */
util_is_noninh_ie(uint8_t elem_id,uint8_t * non_inh_list,int8_t len)2639 static bool util_is_noninh_ie(uint8_t elem_id,
2640 uint8_t *non_inh_list,
2641 int8_t len)
2642 {
2643 int count;
2644
2645 for (count = 0; count < len; count++) {
2646 if (elem_id == non_inh_list[count])
2647 return true;
2648 }
2649
2650 return false;
2651 }
2652
2653 /*
2654 * util_scan_find_noninheritance_ie() - find noninheritance information element
2655 * This block of code is to identify if there is any non-inheritance element
2656 * present as part of the nontransmitted BSSID profile.
2657 * @elem_id: element id
2658 * @ies: pointer consisting of IEs
2659 * @len: IE length
2660 *
2661 * Return: NULL if the element ID is not found or if IE pointer is NULL else
2662 * pointer to the first byte of the requested element
2663 */
2664 static uint8_t
util_scan_find_noninheritance_ie(uint8_t elem_id,uint8_t * ies,int32_t len)2665 *util_scan_find_noninheritance_ie(uint8_t elem_id, uint8_t *ies,
2666 int32_t len)
2667 {
2668 if (!ies)
2669 return NULL;
2670
2671 while ((len >= MIN_IE_LEN + 1) && len >= ies[TAG_LEN_POS] + MIN_IE_LEN)
2672 {
2673 if ((ies[ID_POS] == elem_id) &&
2674 (ies[ELEM_ID_EXTN_POS] ==
2675 WLAN_EXTN_ELEMID_NONINHERITANCE)) {
2676 return ies;
2677 }
2678 len -= ies[TAG_LEN_POS] + MIN_IE_LEN;
2679 ies += ies[TAG_LEN_POS] + MIN_IE_LEN;
2680 }
2681
2682 return NULL;
2683 }
2684 #endif
2685
2686 /*
2687 * util_scan_find_ie() - find information element
2688 * @eid: element id
2689 * @ies: pointer consisting of IEs
2690 * @len: IE length
2691 *
2692 * Return: NULL if the element ID is not found or if IE pointer is NULL else
2693 * pointer to the first byte of the requested element
2694 */
util_scan_find_ie(uint8_t eid,uint8_t * ies,int32_t len)2695 static uint8_t *util_scan_find_ie(uint8_t eid, uint8_t *ies,
2696 int32_t len)
2697 {
2698 if (!ies)
2699 return NULL;
2700
2701 while (len >= 2 && len >= ies[1] + 2) {
2702 if (ies[0] == eid)
2703 return ies;
2704 len -= ies[1] + 2;
2705 ies += ies[1] + 2;
2706 }
2707
2708 return NULL;
2709 }
2710
2711 #ifdef WLAN_FEATURE_MBSSID
util_gen_new_bssid(uint8_t * bssid,uint8_t max_bssid,uint8_t mbssid_index,uint8_t * new_bssid_addr)2712 static void util_gen_new_bssid(uint8_t *bssid, uint8_t max_bssid,
2713 uint8_t mbssid_index,
2714 uint8_t *new_bssid_addr)
2715 {
2716 uint8_t lsb_n;
2717 int i;
2718
2719 for (i = 0; i < QDF_MAC_ADDR_SIZE; i++)
2720 new_bssid_addr[i] = bssid[i];
2721
2722 lsb_n = new_bssid_addr[5] & ((1 << max_bssid) - 1);
2723
2724 new_bssid_addr[5] &= ~((1 << max_bssid) - 1);
2725 new_bssid_addr[5] |= (lsb_n + mbssid_index) % (1 << max_bssid);
2726 }
2727
2728 /*
2729 * util_parse_noninheritance_list() - This block of code will be executed only
2730 * if there is a valid non inheritance IE present in the nontx profile.
2731 * Host need not inherit those list of element IDs and list of element ID
2732 * extensions from the transmitted BSSID profile.
2733 * Since non-inheritance element is an element ID extension, it should
2734 * be part of extension element. So first we need to find if there are
2735 * any extension element present in the nontransmitted BSSID profile.
2736 * @extn_elem: If valid, it points to the element ID field of
2737 * extension element tag in the nontransmitted BSSID profile.
2738 * It may or may not have non inheritance tag present.
2739 * _____________________________________________
2740 * | | | |List of|List of |
2741 * | Element |Length |Element|Element|Element ID |
2742 * | ID | |ID extn| IDs |Extension |
2743 * |_________|_______|_______|_______|___________|
2744 * List of Element IDs:
2745 * __________________
2746 * | | |
2747 * | Length |Element |
2748 * | |ID List |
2749 * |_________|________|
2750 * List of Element ID Extensions:
2751 * __________________________
2752 * | | |
2753 * | Length |Element ID |
2754 * | |extension List |
2755 * |_________|________________|
2756 * @elem_list: Element ID list
2757 * @extn_elem_list: Element ID exiension list
2758 * @non_inheritance_ie: Non inheritance IE information
2759 */
2760
util_parse_noninheritance_list(uint8_t * extn_elem,uint8_t ** elem_list,uint8_t ** extn_elem_list,struct non_inheritance_ie * ninh)2761 static void util_parse_noninheritance_list(uint8_t *extn_elem,
2762 uint8_t **elem_list,
2763 uint8_t **extn_elem_list,
2764 struct non_inheritance_ie *ninh)
2765 {
2766 int8_t extn_rem_len = 0;
2767
2768 if (extn_elem[ELEM_ID_LIST_LEN_POS] < extn_elem[TAG_LEN_POS]) {
2769 /*
2770 * extn_rem_len represents the number of bytes after
2771 * the length subfield of list of Element IDs.
2772 * So here, extn_rem_len should be equal to
2773 * Element ID list + Length subfield of Element ID
2774 * extension list + Element ID extension list.
2775 *
2776 * Here we have taken two pointers pointing to the
2777 * element ID list and element ID extension list
2778 * which we will use to detect the same elements
2779 * in the transmitted BSSID profile and choose not
2780 * to inherit those elements while constructing the
2781 * frame for nontransmitted BSSID profile.
2782 */
2783 extn_rem_len = extn_elem[TAG_LEN_POS] - MIN_IE_LEN;
2784 ninh->non_inherit = true;
2785
2786 if (extn_rem_len && extn_elem[ELEM_ID_LIST_LEN_POS]) {
2787 if (extn_rem_len >= extn_elem[ELEM_ID_LIST_LEN_POS]) {
2788 ninh->list_len =
2789 extn_elem[ELEM_ID_LIST_LEN_POS];
2790 *elem_list = extn_elem + ELEM_ID_LIST_POS;
2791 extn_rem_len -= ninh->list_len;
2792 } else {
2793 /*
2794 * Corrupt frame. length subfield of
2795 * element ID list is greater than
2796 * what it should be. Go ahead with
2797 * frame generation but do not honour
2798 * the non inheritance part. Also, mark
2799 * the element ID in subcopy as 0, so
2800 * that this element info will not
2801 * be copied.
2802 */
2803 ninh->non_inherit = false;
2804 extn_elem[0] = 0;
2805 }
2806 }
2807
2808 extn_rem_len--;
2809 if (extn_rem_len > 0) {
2810 if (!ninh->list_len) {
2811 ninh->extn_len =
2812 extn_elem[ELEM_ID_LIST_LEN_POS + 1];
2813 } else {
2814 ninh->extn_len =
2815 extn_elem[ELEM_ID_LIST_POS +
2816 ninh->list_len];
2817 }
2818
2819 if (extn_rem_len != ninh->extn_len) {
2820 /*
2821 * Corrupt frame. length subfield of
2822 * element ID extn list is not
2823 * what it should be. Go ahead with
2824 * frame generation but do not honour
2825 * the non inheritance part. Also, mark
2826 * the element ID in subcopy as 0, so
2827 * that this element info will not
2828 * be copied.
2829 */
2830 ninh->non_inherit = false;
2831 extn_elem[0] = 0;
2832 }
2833
2834 if (ninh->extn_len) {
2835 *extn_elem_list =
2836 (extn_elem + ninh->list_len +
2837 ELEM_ID_LIST_POS + 1);
2838 }
2839 }
2840 }
2841 }
2842
2843 #ifdef WLAN_FEATURE_11BE_MLO
2844 /**
2845 * util_handle_rnr_ie_for_mbssid() - parse and modify RNR IE for MBSSID feature
2846 * @rnr: The pointer to RNR IE
2847 * @bssid_index: BSSID index from MBSSID index IE
2848 * @pos: The buffer pointer to save the transformed RNR IE, caller is expected
2849 * to supply a buffer that is at least as big as @rnr
2850 *
2851 * Per the description about Neighbor AP Information field about MLD
2852 * parameters subfield in section 9.4.2.170.2 of Draft P802.11be_D1.4.
2853 * If the reported AP is affiliated with the same MLD of the reporting AP,
2854 * the TBTT information is skipped; If the reported AP is affiliated with
2855 * the same MLD of the nontransmitted BSSID, the TBTT information is
2856 * copied and the MLD ID is changed to 0.
2857 *
2858 * Return: Length of the element written to @pos
2859 */
util_handle_rnr_ie_for_mbssid(const uint8_t * rnr,uint8_t bssid_index,uint8_t * pos)2860 static int util_handle_rnr_ie_for_mbssid(const uint8_t *rnr,
2861 uint8_t bssid_index, uint8_t *pos)
2862 {
2863 size_t rnr_len;
2864 const uint8_t *data, *rnr_end;
2865 uint8_t *rnr_new;
2866 struct neighbor_ap_info_field *neighbor_ap_info;
2867 struct rnr_mld_info *mld_param;
2868 uint8_t tbtt_type, tbtt_len, tbtt_count;
2869 uint8_t mld_pos, mld_id;
2870 int32_t i, copy_len;
2871 /* The count of TBTT info field whose MLD ID equals to 0 in a neighbor
2872 * AP information field.
2873 */
2874 uint32_t tbtt_info_field_count;
2875 /* The total bytes of TBTT info fields whose MLD ID equals to 0 in
2876 * current RNR IE.
2877 */
2878 uint32_t tbtt_info_field_len = 0;
2879 uint8_t nbr_ap_info_len = sizeof(struct neighbor_ap_info_field);
2880
2881 rnr_len = rnr[TAG_LEN_POS];
2882 rnr_end = rnr + rnr_len + MIN_IE_LEN;
2883 rnr_new = pos;
2884 qdf_mem_copy(pos, rnr, MIN_IE_LEN);
2885 pos += MIN_IE_LEN;
2886
2887 data = rnr + PAYLOAD_START_POS;
2888 while (data + sizeof(struct neighbor_ap_info_field) <= rnr_end) {
2889 neighbor_ap_info = (struct neighbor_ap_info_field *)data;
2890 tbtt_count = neighbor_ap_info->tbtt_header.tbtt_info_count;
2891 tbtt_len = neighbor_ap_info->tbtt_header.tbtt_info_length;
2892 tbtt_type = neighbor_ap_info->tbtt_header.tbbt_info_fieldtype;
2893 scm_debug("channel number %d, op class %d, bssid_index %d",
2894 neighbor_ap_info->channel_number,
2895 neighbor_ap_info->operting_class, bssid_index);
2896 scm_debug("tbtt_count %d, tbtt_length %d, tbtt_type %d",
2897 tbtt_count, tbtt_len, tbtt_type);
2898
2899 copy_len = tbtt_len * (tbtt_count + 1) +
2900 nbr_ap_info_len;
2901 if (data + copy_len > rnr_end)
2902 return 0;
2903
2904 if (tbtt_len >=
2905 TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD_MLD_PARAM)
2906 mld_pos =
2907 TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD;
2908 else
2909 mld_pos = 0;
2910
2911 /* If MLD params do not exist, copy this neighbor AP
2912 * information field.
2913 * Per Draft P802.11be_D1.4, tbtt_type value 1, 2 and 3
2914 * are reserved,
2915 */
2916 if (mld_pos == 0 || tbtt_type != 0) {
2917 scm_debug("no MLD params, tbtt_type %d", tbtt_type);
2918 qdf_mem_copy(pos, data, copy_len);
2919 pos += copy_len;
2920 data += copy_len;
2921 continue;
2922 }
2923
2924 qdf_mem_copy(pos, data, nbr_ap_info_len);
2925 neighbor_ap_info = (struct neighbor_ap_info_field *)pos;
2926 pos += nbr_ap_info_len;
2927 data += nbr_ap_info_len;
2928
2929 tbtt_info_field_count = 0;
2930 for (i = 0; i < tbtt_count + 1; i++) {
2931 mld_param = (struct rnr_mld_info *)&data[mld_pos];
2932 mld_id = mld_param->mld_id;
2933
2934 /* Refer to Draft P802.11be_D1.4
2935 * 9.4.2.170.2 Neighbor AP Information field about
2936 * MLD parameters subfield
2937 */
2938 if (mld_id == 0) {
2939 /* Skip this TBTT information since this
2940 * reported AP is affiliated with the same MLD
2941 * of the reporting AP who sending the frame
2942 * carrying this element.
2943 */
2944 tbtt_info_field_len += tbtt_len;
2945 data += tbtt_len;
2946 tbtt_info_field_count++;
2947 } else if (mld_id == bssid_index) {
2948 /* Copy this TBTT information and change MLD
2949 * to 0 as this reported AP is affiliated with
2950 * the same MLD of the nontransmitted BSSID.
2951 */
2952 qdf_mem_copy(pos, data, tbtt_len);
2953 mld_param =
2954 (struct rnr_mld_info *)&pos[mld_pos];
2955 scm_debug("change MLD ID from %d to 0",
2956 mld_param->mld_id);
2957 mld_param->mld_id = 0;
2958 data += tbtt_len;
2959 pos += tbtt_len;
2960 } else {
2961 qdf_mem_copy(pos, data, tbtt_len);
2962 data += tbtt_len;
2963 pos += tbtt_len;
2964 }
2965 }
2966
2967 scm_debug("skip %d neighbor info", tbtt_info_field_count);
2968 if (tbtt_info_field_count == (tbtt_count + 1)) {
2969 /* If all the TBTT information are skipped, then also
2970 * revert the neighbor AP info which has been copied.
2971 */
2972 pos -= nbr_ap_info_len;
2973 tbtt_info_field_len += nbr_ap_info_len;
2974 } else {
2975 neighbor_ap_info->tbtt_header.tbtt_info_count -=
2976 tbtt_info_field_count;
2977 }
2978 }
2979
2980 rnr_new[TAG_LEN_POS] = rnr_len - tbtt_info_field_len;
2981 if (rnr_new[TAG_LEN_POS] > 0)
2982 rnr_len = rnr_new[TAG_LEN_POS] + MIN_IE_LEN;
2983 else
2984 rnr_len = 0;
2985
2986 return rnr_len;
2987 }
2988 #else
util_handle_rnr_ie_for_mbssid(const uint8_t * rnr,uint8_t bssid_index,uint8_t * pos)2989 static int util_handle_rnr_ie_for_mbssid(const uint8_t *rnr,
2990 uint8_t bssid_index, uint8_t *pos)
2991 {
2992 return 0;
2993 }
2994 #endif
2995
2996 #ifdef WLAN_FEATURE_ACTION_OUI
util_copy_reporting_ap_vendor_ies(struct wlan_objmgr_psoc * psoc,const uint8_t * ie,uint32_t ie_len,uint8_t * buf_ie)2997 static uint8_t *util_copy_reporting_ap_vendor_ies(struct wlan_objmgr_psoc *psoc,
2998 const uint8_t *ie,
2999 uint32_t ie_len,
3000 uint8_t *buf_ie)
3001 {
3002 struct action_oui_search_attr attr = {0};
3003 enum action_oui_id oui_id = ACTION_OUI_RESTRICT_MAX_MLO_LINKS;
3004
3005 attr.ie_data = (uint8_t *)ie;
3006 attr.ie_length = ie_len;
3007
3008 if (wlan_action_oui_search(psoc, &attr, oui_id)) {
3009 qdf_mem_copy(buf_ie, ie, ie_len);
3010 buf_ie += ie_len;
3011 }
3012
3013 return buf_ie;
3014 }
3015 #else
3016 static inline uint8_t *
util_copy_reporting_ap_vendor_ies(struct wlan_objmgr_psoc * psoc,const uint8_t * ie,uint32_t ie_len,uint8_t * buf_ie)3017 util_copy_reporting_ap_vendor_ies(struct wlan_objmgr_psoc *psoc,
3018 const uint8_t *ie, uint32_t ie_len,
3019 uint8_t *buf_ie)
3020 {
3021 return buf_ie;
3022 }
3023 #endif
3024
util_gen_new_ie(struct wlan_objmgr_pdev * pdev,uint8_t * ie,uint32_t ielen,uint8_t * subelement,size_t subie_len,uint8_t * new_ie,uint8_t bssid_index)3025 static uint32_t util_gen_new_ie(struct wlan_objmgr_pdev *pdev,
3026 uint8_t *ie, uint32_t ielen,
3027 uint8_t *subelement,
3028 size_t subie_len, uint8_t *new_ie,
3029 uint8_t bssid_index)
3030 {
3031 struct wlan_objmgr_psoc *psoc;
3032 uint8_t *pos, *tmp;
3033 const uint8_t *tmp_old, *tmp_new;
3034 uint8_t *sub_copy, *extn_elem = NULL;
3035 struct non_inheritance_ie ninh = {0};
3036 uint8_t *elem_list = NULL, *extn_elem_list = NULL;
3037 size_t tmp_rem_len;
3038
3039 psoc = wlan_pdev_get_psoc(pdev);
3040 if (!psoc) {
3041 scm_err("NULL PSOC");
3042 return 0;
3043 }
3044
3045 /* copy subelement as we need to change its content to
3046 * mark an ie after it is processed.
3047 */
3048 sub_copy = qdf_mem_malloc(subie_len);
3049 if (!sub_copy)
3050 return 0;
3051 qdf_mem_copy(sub_copy, subelement, subie_len);
3052
3053 pos = &new_ie[0];
3054
3055 /* new ssid */
3056 tmp_new = util_scan_find_ie(WLAN_ELEMID_SSID, sub_copy, subie_len);
3057 if (tmp_new) {
3058 scm_debug(" SSID " QDF_SSID_FMT,
3059 QDF_SSID_REF(tmp_new[1],
3060 &tmp_new[PAYLOAD_START_POS]));
3061 if ((pos + tmp_new[1] + MIN_IE_LEN) <=
3062 (new_ie + ielen)) {
3063 qdf_mem_copy(pos, tmp_new,
3064 (tmp_new[1] + MIN_IE_LEN));
3065 pos += (tmp_new[1] + MIN_IE_LEN);
3066 }
3067 }
3068
3069 extn_elem = util_scan_find_noninheritance_ie(WLAN_ELEMID_EXTN_ELEM,
3070 sub_copy, subie_len);
3071
3072 if (extn_elem && extn_elem[TAG_LEN_POS] >= VALID_ELEM_LEAST_LEN) {
3073 if (((extn_elem + extn_elem[1] + MIN_IE_LEN) - sub_copy)
3074 < subie_len)
3075 util_parse_noninheritance_list(extn_elem, &elem_list,
3076 &extn_elem_list, &ninh);
3077 }
3078
3079 /* go through IEs in ie (skip SSID) and subelement,
3080 * merge them into new_ie
3081 */
3082 tmp_old = util_scan_find_ie(WLAN_ELEMID_SSID, ie, ielen);
3083 tmp_old = (tmp_old) ? tmp_old + tmp_old[1] + MIN_IE_LEN : ie;
3084
3085 if (((tmp_old + MIN_IE_LEN) - ie) >= ielen) {
3086 qdf_mem_free(sub_copy);
3087 return 0;
3088 }
3089
3090 while (((tmp_old + tmp_old[1] + MIN_IE_LEN) - ie) <= ielen) {
3091 ninh.non_inh_ie_found = 0;
3092 if (ninh.non_inherit) {
3093 if (ninh.list_len) {
3094 ninh.non_inh_ie_found =
3095 util_is_noninh_ie(tmp_old[0],
3096 elem_list,
3097 ninh.list_len);
3098 }
3099
3100 if (!ninh.non_inh_ie_found &&
3101 ninh.extn_len &&
3102 (tmp_old[0] == WLAN_ELEMID_EXTN_ELEM)) {
3103 ninh.non_inh_ie_found =
3104 util_is_noninh_ie(tmp_old[2],
3105 extn_elem_list,
3106 ninh.extn_len);
3107 }
3108 }
3109
3110 if (ninh.non_inh_ie_found || (tmp_old[0] == 0)) {
3111 if (((tmp_old + tmp_old[1] + MIN_IE_LEN) - ie) >=
3112 (ielen - MIN_IE_LEN))
3113 break;
3114 tmp_old += tmp_old[1] + MIN_IE_LEN;
3115 continue;
3116 }
3117
3118 tmp = (uint8_t *)util_scan_find_ie(tmp_old[0], sub_copy,
3119 subie_len);
3120 if (!tmp) {
3121 /* ie in old ie but not in subelement */
3122 if (tmp_old[0] == WLAN_ELEMID_REDUCED_NEIGHBOR_REPORT) {
3123 /* handle rnr ie for mbssid*/
3124 pos +=
3125 util_handle_rnr_ie_for_mbssid(tmp_old,
3126 bssid_index,
3127 pos);
3128 } else if (tmp_old[0] != WLAN_ELEMID_MULTIPLE_BSSID) {
3129 if ((pos + tmp_old[1] + MIN_IE_LEN) <=
3130 (new_ie + ielen)) {
3131 qdf_mem_copy(pos, tmp_old,
3132 (tmp_old[1] +
3133 MIN_IE_LEN));
3134 pos += tmp_old[1] + MIN_IE_LEN;
3135 }
3136 }
3137 } else {
3138 /* ie in transmitting ie also in subelement,
3139 * copy from subelement and flag the ie in subelement
3140 * as copied (by setting eid field to 0xff).
3141 * To determine if the vendor ies are same:
3142 * 1. For Cisco OUI, compare only OUI + type
3143 * 2. For other OUI, compare OUI + type + subType
3144 */
3145 tmp_rem_len = subie_len - (tmp - sub_copy);
3146 if (tmp_old[0] == WLAN_ELEMID_VENDOR &&
3147 tmp_rem_len >= MIN_VENDOR_TAG_LEN) {
3148 /*
3149 * In order to identify few Vendor APs the
3150 * generated frame should contain the reporting
3151 * APs matching VSIE or else the entry generated
3152 * will not have this VSIE and logic kept to
3153 * take certain action on specific Vendor APs
3154 * will fail.
3155 */
3156 pos = util_copy_reporting_ap_vendor_ies(psoc,
3157 tmp_old,
3158 tmp_old[1] + MIN_IE_LEN,
3159 pos);
3160 /* If Vendor IE also presents in STA profile,
3161 * then ignore the Vendor IE which is for
3162 * reporting STA. It only needs to copy Vendor
3163 * IE from STA profile for reported BSSID.
3164 * The copy happens when going through the
3165 * remaining IEs.
3166 */
3167 } else if (tmp_old[0] == WLAN_ELEMID_EXTN_ELEM &&
3168 tmp_rem_len >= (MIN_IE_LEN + 1)) {
3169 if (tmp_old[PAYLOAD_START_POS] ==
3170 tmp[PAYLOAD_START_POS]) {
3171 /* same ie, copy from subelement */
3172 if ((pos + tmp[1] + MIN_IE_LEN) <=
3173 (new_ie + ielen)) {
3174 qdf_mem_copy(pos, tmp,
3175 tmp[1] +
3176 MIN_IE_LEN);
3177 pos += tmp[1] + MIN_IE_LEN;
3178 tmp[0] = 0;
3179 }
3180 } else {
3181 if ((pos + tmp_old[1] + MIN_IE_LEN) <=
3182 (new_ie + ielen)) {
3183 qdf_mem_copy(pos, tmp_old,
3184 tmp_old[1] +
3185 MIN_IE_LEN);
3186 pos += tmp_old[1] +
3187 MIN_IE_LEN;
3188 }
3189 }
3190
3191 } else {
3192 /* copy ie from subelement into new ie */
3193 if ((pos + tmp[1] + MIN_IE_LEN) <=
3194 (new_ie + ielen)) {
3195 qdf_mem_copy(pos, tmp,
3196 tmp[1] + MIN_IE_LEN);
3197 pos += tmp[1] + MIN_IE_LEN;
3198 tmp[0] = 0;
3199 }
3200 }
3201 }
3202
3203 if (((tmp_old + tmp_old[1] + MIN_IE_LEN) - ie) >=
3204 (ielen - MIN_IE_LEN))
3205 break;
3206
3207 tmp_old += tmp_old[1] + MIN_IE_LEN;
3208 }
3209
3210 /* go through subelement again to check if there is any ie not
3211 * copied to new ie, skip ssid, capability, bssid-index ie
3212 */
3213 tmp_new = sub_copy;
3214 while ((subie_len > 0) &&
3215 (((tmp_new + tmp_new[1] + MIN_IE_LEN) - sub_copy) <=
3216 subie_len)) {
3217 if (!(tmp_new[0] == WLAN_ELEMID_NONTX_BSSID_CAP ||
3218 tmp_new[0] == WLAN_ELEMID_SSID ||
3219 tmp_new[0] == WLAN_ELEMID_MULTI_BSSID_IDX ||
3220 ((tmp_new[0] == WLAN_ELEMID_EXTN_ELEM) &&
3221 (tmp_new[2] == WLAN_EXTN_ELEMID_NONINHERITANCE)))) {
3222 if ((pos + tmp_new[1] + MIN_IE_LEN) <=
3223 (new_ie + ielen)) {
3224 qdf_mem_copy(pos, tmp_new,
3225 tmp_new[1] + MIN_IE_LEN);
3226 pos += tmp_new[1] + MIN_IE_LEN;
3227 }
3228 }
3229 if (((tmp_new + tmp_new[1] + MIN_IE_LEN) - sub_copy) >=
3230 (subie_len - 1))
3231 break;
3232 tmp_new += tmp_new[1] + MIN_IE_LEN;
3233 }
3234
3235 qdf_mem_free(sub_copy);
3236
3237 if (pos > new_ie)
3238 return pos - new_ie;
3239 else
3240 return 0;
3241 }
3242
3243 static enum nontx_profile_reasoncode
util_handle_nontx_prof(uint8_t * mbssid_elem,uint8_t * subelement,uint8_t * next_subelement,struct scan_mbssid_info * mbssid_info,char * bssid,char * new_bssid)3244 util_handle_nontx_prof(uint8_t *mbssid_elem, uint8_t *subelement,
3245 uint8_t *next_subelement,
3246 struct scan_mbssid_info *mbssid_info,
3247 char *bssid, char *new_bssid)
3248 {
3249 uint8_t *mbssid_index_ie;
3250 uint32_t prof_len;
3251
3252 prof_len = subelement[TAG_LEN_POS];
3253 /*
3254 * If we are executing the split portion of the nontx
3255 * profile present in the subsequent MBSSID, then there
3256 * is no need of any sanity check for valid BSS profile
3257 */
3258
3259 if (mbssid_info->split_prof_continue) {
3260 if ((subelement[ID_POS] != 0) ||
3261 (subelement[TAG_LEN_POS] < SPLIT_PROF_DATA_LEAST_LEN)) {
3262 return INVALID_SPLIT_PROF;
3263 }
3264 } else {
3265 if ((subelement[ID_POS] != 0) ||
3266 (subelement[TAG_LEN_POS] < VALID_ELEM_LEAST_LEN)) {
3267 /* not a valid BSS profile */
3268 return INVALID_NONTX_PROF;
3269 }
3270 }
3271
3272 if (mbssid_info->split_profile) {
3273 if (next_subelement[PAYLOAD_START_POS] !=
3274 WLAN_ELEMID_NONTX_BSSID_CAP) {
3275 mbssid_info->prof_residue = true;
3276 }
3277 }
3278
3279 if (!mbssid_info->split_prof_continue &&
3280 ((subelement[PAYLOAD_START_POS] != WLAN_ELEMID_NONTX_BSSID_CAP) ||
3281 (subelement[NONTX_BSSID_CAP_TAG_LEN_POS] != CAP_INFO_LEN))) {
3282 /* The first element within the Nontransmitted
3283 * BSSID Profile is not the Nontransmitted
3284 * BSSID Capability element.
3285 */
3286 return INVALID_NONTX_PROF;
3287 }
3288
3289 /* found a Nontransmitted BSSID Profile */
3290 mbssid_index_ie =
3291 util_scan_find_ie(WLAN_ELEMID_MULTI_BSSID_IDX,
3292 (subelement + PAYLOAD_START_POS), prof_len);
3293
3294 if (!mbssid_index_ie) {
3295 if (!mbssid_info->prof_residue)
3296 return INVALID_NONTX_PROF;
3297
3298 mbssid_info->skip_bssid_copy = true;
3299 } else if ((mbssid_index_ie[TAG_LEN_POS] < 1) ||
3300 (mbssid_index_ie[BSS_INDEX_POS] == 0)) {
3301 /* No valid Multiple BSSID-Index element */
3302 return INVALID_NONTX_PROF;
3303 }
3304
3305 if (!mbssid_info->skip_bssid_copy) {
3306 qdf_mem_copy(mbssid_info->trans_bssid,
3307 bssid, QDF_MAC_ADDR_SIZE);
3308 mbssid_info->profile_num =
3309 mbssid_index_ie[BSS_INDEX_POS];
3310 util_gen_new_bssid(bssid,
3311 mbssid_elem[MBSSID_INDICATOR_POS],
3312 mbssid_index_ie[BSS_INDEX_POS],
3313 new_bssid);
3314 qdf_mem_copy(mbssid_info->non_trans_bssid, new_bssid,
3315 QDF_MAC_ADDR_SIZE);
3316 }
3317 /* In single MBSS IE, there could be subelement holding
3318 * remaining vendor IEs of non tx profile from last MBSS IE
3319 * [split profile] and new non tx profile, hence reset
3320 * skip_bssid_copy flag after each subelement processing
3321 */
3322 mbssid_info->skip_bssid_copy = false;
3323 return VALID_NONTX_PROF;
3324 }
3325
3326 /*
3327 * What's split profile:
3328 * If any nontransmitted BSSID profile is fragmented across
3329 * multiple MBSSID elements, then it is called split profile.
3330 * For a split profile to exist we need to have at least two
3331 * MBSSID elements as part of the RX beacon or probe response
3332 * Hence, first we need to identify the next MBSSID element
3333 * and check for the 5th bit from the starting of the next
3334 * MBSSID IE and if it does not have Nontransmitted BSSID
3335 * capability element, then it's a split profile case.
3336 */
util_scan_is_split_prof_found(uint8_t * next_elem,uint8_t * ie,uint32_t ielen)3337 static bool util_scan_is_split_prof_found(uint8_t *next_elem,
3338 uint8_t *ie, uint32_t ielen)
3339 {
3340 uint8_t *next_mbssid_elem;
3341
3342 if ((next_elem + MIN_IE_LEN + VALID_ELEM_LEAST_LEN) > (ie + ielen))
3343 return false;
3344
3345 if (next_elem[0] == WLAN_ELEMID_MULTIPLE_BSSID) {
3346 if ((next_elem[TAG_LEN_POS] >= VALID_ELEM_LEAST_LEN) &&
3347 (next_elem[SUBELEM_DATA_POS_FROM_MBSSID] !=
3348 WLAN_ELEMID_NONTX_BSSID_CAP)) {
3349 return true;
3350 }
3351 } else {
3352 next_mbssid_elem =
3353 util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID,
3354 next_elem,
3355 ielen - (next_elem - ie));
3356 if (!next_mbssid_elem)
3357 return false;
3358
3359 if ((next_mbssid_elem[TAG_LEN_POS] >= VALID_ELEM_LEAST_LEN) &&
3360 (next_mbssid_elem[SUBELEM_DATA_POS_FROM_MBSSID] !=
3361 WLAN_ELEMID_NONTX_BSSID_CAP)) {
3362 return true;
3363 }
3364 }
3365
3366 return false;
3367 }
3368
util_scan_parse_mbssid(struct wlan_objmgr_pdev * pdev,uint8_t * frame,qdf_size_t frame_len,uint32_t frm_subtype,struct mgmt_rx_event_params * rx_param,qdf_list_t * scan_list)3369 static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev,
3370 uint8_t *frame, qdf_size_t frame_len,
3371 uint32_t frm_subtype,
3372 struct mgmt_rx_event_params *rx_param,
3373 qdf_list_t *scan_list)
3374 {
3375 struct wlan_scan_obj *scan_obj;
3376 struct wlan_bcn_frame *bcn;
3377 struct wlan_frame_hdr *hdr;
3378 struct scan_mbssid_info mbssid_info = {0};
3379 QDF_STATUS status;
3380 uint8_t *pos, *subelement, *next_elem;
3381 uint8_t *mbssid_elem;
3382 uint32_t subie_len, new_ie_len, ielen;
3383 uint8_t *next_subelement = NULL;
3384 uint8_t new_bssid[QDF_MAC_ADDR_SIZE], bssid[QDF_MAC_ADDR_SIZE];
3385 uint8_t *new_ie, *split_prof_start = NULL, *split_prof_end = NULL;
3386 uint8_t *ie, *new_frame = NULL;
3387 int new_frame_len = 0, split_prof_len = 0;
3388 enum nontx_profile_reasoncode retval;
3389 uint8_t *nontx_profile = NULL;
3390
3391 scan_obj = wlan_pdev_get_scan_obj(pdev);
3392 if (!scan_obj)
3393 return QDF_STATUS_E_INVAL;
3394
3395 hdr = (struct wlan_frame_hdr *)frame;
3396 bcn = (struct wlan_bcn_frame *)(frame + sizeof(struct wlan_frame_hdr));
3397 ie = (uint8_t *)&bcn->ie;
3398 ielen = (uint16_t)(frame_len -
3399 sizeof(struct wlan_frame_hdr) -
3400 offsetof(struct wlan_bcn_frame, ie));
3401 qdf_mem_copy(bssid, hdr->i_addr3, QDF_MAC_ADDR_SIZE);
3402
3403 if (!util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, ie, ielen))
3404 return QDF_STATUS_E_FAILURE;
3405
3406 pos = ie;
3407
3408 new_ie = qdf_mem_malloc(ielen);
3409 if (!new_ie)
3410 return QDF_STATUS_E_NOMEM;
3411
3412 while (pos < (ie + ielen + MIN_IE_LEN)) {
3413 mbssid_elem =
3414 util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, pos,
3415 ielen - (pos - ie));
3416 if (!mbssid_elem)
3417 break;
3418
3419 /*
3420 * The max_bssid_indicator field is mandatory, therefore the
3421 * length of the MBSSID element should atleast be 1.
3422 */
3423 if (!mbssid_elem[TAG_LEN_POS]) {
3424 scm_debug_rl("MBSSID IE is of length zero");
3425 break;
3426 }
3427
3428 mbssid_info.profile_count =
3429 (1 << mbssid_elem[MBSSID_INDICATOR_POS]);
3430
3431 next_elem =
3432 mbssid_elem + mbssid_elem[TAG_LEN_POS] + MIN_IE_LEN;
3433
3434 /* Skip Element ID, Len, MaxBSSID Indicator */
3435 if (!mbssid_info.split_profile &&
3436 (mbssid_elem[TAG_LEN_POS] < VALID_ELEM_LEAST_LEN)) {
3437 break;
3438 }
3439
3440 /*
3441 * Find if the next IE is MBSSID, if not, then scan through
3442 * the IE list and find the next MBSSID tag, if present.
3443 * Once we find the MBSSID tag, check if this MBSSID tag has
3444 * the other fragmented part of the non Tx profile.
3445 */
3446
3447 mbssid_info.split_profile =
3448 util_scan_is_split_prof_found(next_elem, ie, ielen);
3449
3450 for (subelement = mbssid_elem + SUBELEMENT_START_POS;
3451 subelement < (next_elem - 1);
3452 subelement += MIN_IE_LEN + subelement[TAG_LEN_POS]) {
3453 subie_len = subelement[TAG_LEN_POS];
3454
3455 /*
3456 * if prof_residue is true, that means we are
3457 * in the continuation of the fragmented profile part,
3458 * present in the next MBSSD IE else this profile
3459 * is a non fragmented non tx BSSID profile.
3460 */
3461
3462 if (mbssid_info.prof_residue)
3463 mbssid_info.split_prof_continue = true;
3464 else
3465 mbssid_info.split_prof_continue = false;
3466
3467 if (subie_len > MAX_SUBELEM_LEN) {
3468 scm_debug_rl("Corrupt frame with subie_len: %d "
3469 "split_prof_continue: %d,prof_residue: %d",
3470 subie_len,
3471 mbssid_info.split_prof_continue,
3472 mbssid_info.prof_residue);
3473 if (mbssid_info.split_prof_continue) {
3474 qdf_mem_free(split_prof_start);
3475 split_prof_start = NULL;
3476 }
3477
3478 qdf_mem_free(new_ie);
3479 return QDF_STATUS_E_INVAL;
3480 }
3481
3482 if ((next_elem - subelement) <
3483 (MIN_IE_LEN + subie_len))
3484 break;
3485
3486 next_subelement = subelement + subie_len + MIN_IE_LEN;
3487 retval = util_handle_nontx_prof(mbssid_elem, subelement,
3488 next_subelement,
3489 &mbssid_info,
3490 bssid, new_bssid);
3491
3492 if (retval == INVALID_SPLIT_PROF) {
3493 scm_debug_rl("Corrupt frame with ID_POS: %d,TAG_LEN_POS: %d",
3494 subelement[ID_POS],
3495 subelement[TAG_LEN_POS]);
3496 qdf_mem_free(split_prof_start);
3497 split_prof_start = NULL;
3498 qdf_mem_free(new_ie);
3499 return QDF_STATUS_E_INVAL;
3500 } else if (retval == INVALID_NONTX_PROF) {
3501 continue;
3502 }
3503
3504 /*
3505 * Merging parts of nontx profile-
3506 * Just for understanding, let's make an assumption
3507 * that nontx profile is fragmented across MBSSIE1
3508 * and MBSSIE2.
3509 * mbssid_info.prof_residue being set indicates
3510 * that the ongoing nontx profile is part of split
3511 * profile, whose other fragmented part is present
3512 * in MBSSIE2.
3513 * So once prof_residue is set, we need to
3514 * identify whether we are accessing the split
3515 * profile in MBSSIE1 or MBSSIE2.
3516 * If we are in MBSSIE1, then copy the part of split
3517 * profile from MBSSIE1 into a new buffer and then
3518 * move to the next part of the split profile which
3519 * is present in MBSSIE2 and append that part into
3520 * the new buffer.
3521 * Once the full profile is accumulated, go ahead with
3522 * the ie generation and length calculation of the
3523 * new frame.
3524 */
3525
3526 if (mbssid_info.prof_residue) {
3527 if (!mbssid_info.split_prof_continue) {
3528 split_prof_start =
3529 qdf_mem_malloc(ielen);
3530 if (!split_prof_start) {
3531 scm_err_rl("Malloc failed");
3532 qdf_mem_free(new_ie);
3533 return QDF_STATUS_E_NOMEM;
3534 }
3535
3536 qdf_mem_copy(split_prof_start,
3537 subelement,
3538 (subie_len +
3539 MIN_IE_LEN));
3540 split_prof_end = (split_prof_start +
3541 subie_len +
3542 MIN_IE_LEN);
3543 break;
3544 }
3545
3546 /*
3547 * Currently we are accessing other part of the
3548 * split profile present in the subsequent
3549 * MBSSIE. There is a possibility that one
3550 * non tx profile is spread across more than
3551 * two MBSSID tag as well. This code will
3552 * handle such scenario.
3553 */
3554
3555 if (split_prof_end) {
3556 qdf_mem_copy(split_prof_end,
3557 (subelement + MIN_IE_LEN),
3558 subie_len);
3559 split_prof_end += subie_len;
3560 }
3561
3562 /*
3563 * When to stop the process of accumulating
3564 * parts of split profile, is decided by
3565 * mbssid_info.prof_residue. prof_residue
3566 * could be made false if there is not any
3567 * continuation of the split profile.
3568 * which could be identified by two factors
3569 * 1. By checking if the next MBSSIE's first
3570 * non tx profile is not a fragmented one or
3571 * 2. there is a probability that first
3572 * subelement of MBSSIE2 is end if split
3573 * profile and the next subelement of MBSSIE2
3574 * is a non split one.
3575 */
3576
3577 if (!mbssid_info.split_profile ||
3578 (next_subelement[PAYLOAD_START_POS] ==
3579 WLAN_ELEMID_NONTX_BSSID_CAP)) {
3580 mbssid_info.prof_residue = false;
3581 }
3582
3583 /*
3584 * Until above mentioned conditions are met,
3585 * we need to iterate and keep accumulating
3586 * the split profile contents.
3587 */
3588
3589 if (mbssid_info.prof_residue)
3590 break;
3591
3592 if (split_prof_end) {
3593 split_prof_len =
3594 (split_prof_end -
3595 split_prof_start - MIN_IE_LEN);
3596 }
3597 }
3598
3599 if (mbssid_info.split_prof_continue) {
3600 if (!split_prof_start)
3601 break;
3602 nontx_profile = split_prof_start;
3603 subie_len = split_prof_len;
3604 } else {
3605 nontx_profile = subelement;
3606 }
3607
3608 new_ie_len =
3609 util_gen_new_ie(pdev, ie, ielen,
3610 (nontx_profile +
3611 PAYLOAD_START_POS),
3612 subie_len, new_ie,
3613 mbssid_info.profile_num);
3614
3615 if (!new_ie_len) {
3616 if (mbssid_info.split_prof_continue) {
3617 qdf_mem_free(split_prof_start);
3618 split_prof_start = NULL;
3619 split_prof_end = NULL;
3620 split_prof_len = 0;
3621 }
3622 continue;
3623 }
3624
3625 new_frame_len = frame_len - ielen + new_ie_len;
3626
3627 if (new_frame_len < 0 || new_frame_len > frame_len) {
3628 if (mbssid_info.split_prof_continue) {
3629 qdf_mem_free(split_prof_start);
3630 split_prof_start = NULL;
3631 }
3632 qdf_mem_free(new_ie);
3633 scm_debug_rl("Invalid frame:Stop MBSSIE parsing, Frame_len: %zu "
3634 "ielen:%u,new_ie_len:%u",
3635 frame_len, ielen, new_ie_len);
3636 return QDF_STATUS_E_INVAL;
3637 }
3638
3639 new_frame = qdf_mem_malloc(new_frame_len);
3640 if (!new_frame) {
3641 if (mbssid_info.split_prof_continue) {
3642 qdf_mem_free(split_prof_start);
3643 split_prof_start = NULL;
3644 }
3645 qdf_mem_free(new_ie);
3646 scm_err_rl("Malloc for new_frame failed");
3647 scm_err_rl("split_prof_continue: %d",
3648 mbssid_info.split_prof_continue);
3649 return QDF_STATUS_E_NOMEM;
3650 }
3651
3652 /*
3653 * Copy the header(24byte), timestamp(8 byte),
3654 * beaconinterval(2byte) and capability(2byte)
3655 */
3656 qdf_mem_copy(new_frame, frame, FIXED_LENGTH);
3657 /* Copy the new ie generated from MBSSID profile*/
3658 hdr = (struct wlan_frame_hdr *)new_frame;
3659 qdf_mem_copy(hdr->i_addr2, new_bssid,
3660 QDF_MAC_ADDR_SIZE);
3661 qdf_mem_copy(hdr->i_addr3, new_bssid,
3662 QDF_MAC_ADDR_SIZE);
3663 bcn = (struct wlan_bcn_frame *)
3664 (new_frame + sizeof(struct wlan_frame_hdr));
3665 /* update the non-tx capability */
3666 qdf_mem_copy(&bcn->capability,
3667 nontx_profile + CAP_INFO_POS,
3668 CAP_INFO_LEN);
3669
3670 /* Copy the new ie generated from MBSSID profile*/
3671 qdf_mem_copy(new_frame +
3672 offsetof(struct wlan_bcn_frame, ie) +
3673 sizeof(struct wlan_frame_hdr),
3674 new_ie, new_ie_len);
3675 if (scan_obj->cb.inform_mbssid_bcn_prb_rsp)
3676 scan_obj->cb.inform_mbssid_bcn_prb_rsp(
3677 new_frame, new_frame_len,
3678 frm_subtype, new_bssid);
3679
3680 status = util_scan_gen_scan_entry(pdev, new_frame,
3681 new_frame_len,
3682 frm_subtype,
3683 rx_param,
3684 &mbssid_info,
3685 scan_list);
3686 if (QDF_IS_STATUS_ERROR(status)) {
3687 if (mbssid_info.split_prof_continue) {
3688 qdf_mem_free(split_prof_start);
3689 split_prof_start = NULL;
3690 split_prof_end = NULL;
3691 split_prof_len = 0;
3692 qdf_mem_zero(&mbssid_info,
3693 sizeof(mbssid_info));
3694 }
3695 qdf_mem_free(new_frame);
3696 scm_debug_rl("failed to generate a scan entry "
3697 "split_prof_continue: %d",
3698 mbssid_info.split_prof_continue);
3699 break;
3700 }
3701 /* scan entry makes its own copy so free the frame*/
3702 if (mbssid_info.split_prof_continue) {
3703 qdf_mem_free(split_prof_start);
3704 split_prof_start = NULL;
3705 split_prof_end = NULL;
3706 split_prof_len = 0;
3707 }
3708 qdf_mem_free(new_frame);
3709 }
3710
3711 pos = next_elem;
3712 }
3713 qdf_mem_free(new_ie);
3714
3715 if (split_prof_start)
3716 qdf_mem_free(split_prof_start);
3717
3718 return QDF_STATUS_SUCCESS;
3719 }
3720 #else
util_scan_parse_mbssid(struct wlan_objmgr_pdev * pdev,uint8_t * frame,qdf_size_t frame_len,uint32_t frm_subtype,struct mgmt_rx_event_params * rx_param,qdf_list_t * scan_list)3721 static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev,
3722 uint8_t *frame, qdf_size_t frame_len,
3723 uint32_t frm_subtype,
3724 struct mgmt_rx_event_params *rx_param,
3725 qdf_list_t *scan_list)
3726 {
3727 return QDF_STATUS_SUCCESS;
3728 }
3729 #endif
3730
3731 #if defined(WLAN_FEATURE_11BE) && defined(WLAN_FEATURE_11BE_MLO_MBSSID)
3732 /*
3733 * util_scan_gen_txvap_scan_entry() - Strip out the MBSSID tag from the received
3734 * frame and update the modified frame length before generating a scan entry.
3735 * It is redundant to have MBSSID information as part of the TX vap/ profile
3736 * specific scan entry.
3737 *
3738 * @pdev: pdev context
3739 * @frame: Unsoiled frame passed from util_scan_parse_beacon_frame()
3740 * @frame_len: Length of the unsoiled frame
3741 * @ie_list: Points to the start of IE list in parent/ unsoiled frame
3742 * @ielen: Length of the complete IE list from parent/ unsoiled frame
3743 * @frm_subtype: Frame subtype
3744 * @rx_param: host mgmt header params
3745 * @scan_list: Scan entry list of bss candidates after filtering
3746 * @mbssid_info: Data structure to carry MBSSID information
3747 *
3748 * Return: False if the scan entry generation is not successful
3749 */
3750 static QDF_STATUS
util_scan_gen_txvap_scan_entry(struct wlan_objmgr_pdev * pdev,uint8_t * frame,qdf_size_t frame_len,uint8_t * ie_list,uint32_t ielen,uint32_t frm_subtype,struct mgmt_rx_event_params * rx_param,qdf_list_t * scan_list,struct scan_mbssid_info * mbssid_info)3751 util_scan_gen_txvap_scan_entry(struct wlan_objmgr_pdev *pdev,
3752 uint8_t *frame, qdf_size_t frame_len,
3753 uint8_t *ie_list, uint32_t ielen,
3754 uint32_t frm_subtype,
3755 struct mgmt_rx_event_params *rx_param,
3756 qdf_list_t *scan_list,
3757 struct scan_mbssid_info *mbssid_info)
3758 {
3759 uint8_t *src_ie, *dest_ptr, *container;
3760 uint16_t new_frame_len, new_ie_len = 0;
3761 uint8_t *trimmed_frame, fixed_len = 0;
3762 QDF_STATUS status = QDF_STATUS_SUCCESS;
3763
3764 /*
3765 * Allocate a buffer to copy only the TX VAP information after
3766 * stripping out the MBSSID IE from the parent beacon.
3767 * The allocation size should be the size of a frame as at
3768 * this point it is unknown what would be the new frame length
3769 * after stripping the MBSSID IE.
3770 */
3771 container = qdf_mem_malloc(frame_len);
3772 if (!container) {
3773 scm_err_rl("Malloc for container failed");
3774 return QDF_STATUS_E_NOMEM;
3775 }
3776
3777 dest_ptr = &container[0];
3778 fixed_len = sizeof(struct wlan_frame_hdr) +
3779 offsetof(struct wlan_bcn_frame, ie);
3780
3781 /*Copy the data till IE list before procesisng the IE one by one*/
3782 qdf_mem_copy(dest_ptr, frame, fixed_len);
3783
3784 dest_ptr += fixed_len;
3785 src_ie = ie_list;
3786
3787 /*
3788 * Go through the IE list from the parent beacon and copy one by one.
3789 * Skip copying it to the container if it's an MBSSID tag.
3790 */
3791 while (((src_ie + src_ie[TAG_LEN_POS] + MIN_IE_LEN) -
3792 ie_list) <= ielen) {
3793 if (src_ie[ID_POS] == WLAN_ELEMID_MULTIPLE_BSSID) {
3794 src_ie += src_ie[TAG_LEN_POS] + MIN_IE_LEN;
3795 continue;
3796 }
3797
3798 qdf_mem_copy(dest_ptr, src_ie,
3799 (src_ie[TAG_LEN_POS] + MIN_IE_LEN));
3800
3801 dest_ptr += src_ie[TAG_LEN_POS] + MIN_IE_LEN;
3802 if (((src_ie + src_ie[TAG_LEN_POS] +
3803 MIN_IE_LEN) - ie_list) >= ielen)
3804 break;
3805
3806 src_ie += src_ie[TAG_LEN_POS] + MIN_IE_LEN;
3807 }
3808
3809 if (dest_ptr > container)
3810 new_ie_len = dest_ptr - (container + fixed_len);
3811
3812 new_frame_len = frame_len - ielen + new_ie_len;
3813
3814 /*
3815 * At the start of this handler, we have allocated a memory block
3816 * of size same as a full beacon frame size, as we are not sure
3817 * of what would be the size of the new frame. After stripping out
3818 * the MBSSID tag from the parent beacon, there are some unused
3819 * memory. Hence do another malloc of the new frame length
3820 * (length of the new frame which has only TX VAP information)
3821 * and copy the needed data from the container, then free the
3822 * memory corresponds to container.
3823 * Post copy, use the trimmed frame and the new frame length
3824 * to generate scan entry for the TX profile.
3825 */
3826 trimmed_frame = qdf_mem_malloc(new_frame_len);
3827 if (!trimmed_frame) {
3828 scm_err_rl("Malloc for trimmed frame failed");
3829 qdf_mem_free(container);
3830 return QDF_STATUS_E_NOMEM;
3831 }
3832
3833 qdf_mem_copy(trimmed_frame, container, new_frame_len);
3834 qdf_mem_free(container);
3835
3836 status = util_scan_gen_scan_entry(pdev, trimmed_frame,
3837 new_frame_len,
3838 frm_subtype,
3839 rx_param,
3840 mbssid_info,
3841 scan_list);
3842
3843 if (QDF_IS_STATUS_ERROR(status))
3844 scm_debug_rl("Failed to create a scan entry");
3845
3846 qdf_mem_free(trimmed_frame);
3847 return status;
3848 }
3849
3850 /*
3851 * util_scan_parse_eht_beacon() : This API will be executed
3852 * only for 11BE platforms as per current design.
3853 * IF MBSSID IE is present in the beacon then
3854 * scan component will create a new entry for
3855 * each BSSID found in the MBSSID
3856 * util_scan_parse_mbssid() takes care of creating
3857 * scan entries for every non tx profile present in
3858 * the MBSSID tag.
3859 * util_scan_gen_txvap_scan_entry() helps in generating
3860 * scan entry for the tx profile.
3861 */
3862 static QDF_STATUS
util_scan_parse_eht_beacon(struct wlan_objmgr_pdev * pdev,uint8_t * frame,qdf_size_t frame_len,uint8_t * ie_list,uint32_t ielen,uint32_t frm_subtype,struct mgmt_rx_event_params * rx_param,qdf_list_t * scan_list,struct scan_mbssid_info * mbssid_info,uint8_t * mbssid_ie)3863 util_scan_parse_eht_beacon(struct wlan_objmgr_pdev *pdev,
3864 uint8_t *frame, qdf_size_t frame_len,
3865 uint8_t *ie_list, uint32_t ielen,
3866 uint32_t frm_subtype,
3867 struct mgmt_rx_event_params *rx_param,
3868 qdf_list_t *scan_list,
3869 struct scan_mbssid_info *mbssid_info,
3870 uint8_t *mbssid_ie)
3871 {
3872 QDF_STATUS status = QDF_STATUS_SUCCESS;
3873
3874 if (mbssid_ie && ie_list) {
3875 if (ie_list[TAG_LEN_POS] <= 0) {
3876 scm_debug_rl("Corrupt IE");
3877 return QDF_STATUS_E_INVAL;
3878 }
3879
3880 status = util_scan_parse_mbssid(pdev, frame, frame_len,
3881 frm_subtype, rx_param,
3882 scan_list);
3883
3884 if (QDF_IS_STATUS_ERROR(status)) {
3885 scm_debug_rl("NonTx prof: Failed to create scan entry");
3886 return status;
3887 }
3888
3889 status = util_scan_gen_txvap_scan_entry(pdev, frame,
3890 frame_len, ie_list,
3891 ielen, frm_subtype,
3892 rx_param, scan_list,
3893 mbssid_info);
3894
3895 if (QDF_IS_STATUS_ERROR(status))
3896 scm_debug_rl("TX prof: Failed to create scan entry");
3897
3898 return status;
3899 }
3900
3901 /*For Non MBSSIE case*/
3902 status = util_scan_gen_scan_entry(pdev, frame, frame_len,
3903 frm_subtype, rx_param,
3904 mbssid_info, scan_list);
3905
3906 if (QDF_IS_STATUS_ERROR(status))
3907 scm_debug_rl("Non-MBSSIE frame: Failed to create scan entry");
3908
3909 return status;
3910 }
3911
3912 static bool
util_scan_is_platform_eht_capable(struct wlan_objmgr_pdev * pdev)3913 util_scan_is_platform_eht_capable(struct wlan_objmgr_pdev *pdev)
3914 {
3915 struct wlan_objmgr_psoc *psoc = NULL;
3916 struct wlan_lmac_if_tx_ops *tx_ops = NULL;
3917 struct wlan_lmac_if_scan_tx_ops *scan_ops = NULL;
3918 uint8_t pdev_id;
3919
3920 psoc = wlan_pdev_get_psoc(pdev);
3921 if (!psoc) {
3922 scm_debug_rl("psoc is null");
3923 return false;
3924 }
3925 tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
3926 if (!tx_ops) {
3927 scm_debug_rl("tx_ops is null");
3928 return false;
3929 }
3930 scan_ops = &tx_ops->scan;
3931 if (!scan_ops) {
3932 scm_debug_rl("scan_ops is null");
3933 return false;
3934 }
3935 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
3936
3937 if (scan_ops->is_platform_eht_capable)
3938 return scan_ops->is_platform_eht_capable(psoc, pdev_id);
3939
3940 return false;
3941 }
3942 #else
3943 static QDF_STATUS
util_scan_parse_eht_beacon(struct wlan_objmgr_pdev * pdev,uint8_t * frame,qdf_size_t frame_len,uint8_t * ie_list,uint32_t ielen,uint32_t frm_subtype,struct mgmt_rx_event_params * rx_param,qdf_list_t * scan_list,struct scan_mbssid_info * mbssid_info,uint8_t * mbssid_ie)3944 util_scan_parse_eht_beacon(struct wlan_objmgr_pdev *pdev,
3945 uint8_t *frame, qdf_size_t frame_len,
3946 uint8_t *ie_list, uint32_t ielen,
3947 uint32_t frm_subtype,
3948 struct mgmt_rx_event_params *rx_param,
3949 qdf_list_t *scan_list,
3950 struct scan_mbssid_info *mbssid_info,
3951 uint8_t *mbssid_ie)
3952 {
3953 return QDF_STATUS_SUCCESS;
3954 }
3955
3956 static bool
util_scan_is_platform_eht_capable(struct wlan_objmgr_pdev * pdev)3957 util_scan_is_platform_eht_capable(struct wlan_objmgr_pdev *pdev)
3958 {
3959 return false;
3960 }
3961 #endif
3962
3963 static QDF_STATUS
util_scan_parse_beacon_frame(struct wlan_objmgr_pdev * pdev,uint8_t * frame,qdf_size_t frame_len,uint32_t frm_subtype,struct mgmt_rx_event_params * rx_param,qdf_list_t * scan_list)3964 util_scan_parse_beacon_frame(struct wlan_objmgr_pdev *pdev,
3965 uint8_t *frame,
3966 qdf_size_t frame_len,
3967 uint32_t frm_subtype,
3968 struct mgmt_rx_event_params *rx_param,
3969 qdf_list_t *scan_list)
3970 {
3971 struct wlan_bcn_frame *bcn;
3972 struct wlan_frame_hdr *hdr;
3973 uint8_t *mbssid_ie = NULL, *extcap_ie;
3974 uint32_t ie_len = 0;
3975 QDF_STATUS status = QDF_STATUS_E_FAILURE;
3976 struct scan_mbssid_info mbssid_info = { 0 };
3977 uint8_t *ie_list;
3978 bool eht_support = false;
3979
3980 hdr = (struct wlan_frame_hdr *)frame;
3981 bcn = (struct wlan_bcn_frame *)
3982 (frame + sizeof(struct wlan_frame_hdr));
3983 ie_list = (uint8_t *)&bcn->ie;
3984 ie_len = (uint16_t)(frame_len -
3985 sizeof(struct wlan_frame_hdr) -
3986 offsetof(struct wlan_bcn_frame, ie));
3987
3988 extcap_ie = util_scan_find_ie(WLAN_ELEMID_XCAPS,
3989 (uint8_t *)&bcn->ie, ie_len);
3990 /* Process MBSSID when Multiple BSSID (Bit 22) is set in Ext Caps */
3991 if (extcap_ie &&
3992 extcap_ie[1] >= 3 && extcap_ie[1] <= WLAN_EXTCAP_IE_MAX_LEN &&
3993 (extcap_ie[4] & 0x40)) {
3994 mbssid_ie = util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID,
3995 (uint8_t *)&bcn->ie, ie_len);
3996 if (mbssid_ie) {
3997 /* some APs announce the MBSSID ie_len as 1 */
3998 if (mbssid_ie[TAG_LEN_POS] < 1) {
3999 scm_debug("MBSSID IE length is wrong %d",
4000 mbssid_ie[TAG_LEN_POS]);
4001 return status;
4002 }
4003 qdf_mem_copy(&mbssid_info.trans_bssid,
4004 hdr->i_addr3, QDF_MAC_ADDR_SIZE);
4005 mbssid_info.profile_count = 1 << mbssid_ie[2];
4006 }
4007 }
4008
4009 eht_support = util_scan_is_platform_eht_capable(pdev);
4010
4011 if (eht_support) {
4012 status = util_scan_parse_eht_beacon(pdev, frame, frame_len,
4013 ie_list, ie_len,
4014 frm_subtype, rx_param,
4015 scan_list, &mbssid_info,
4016 mbssid_ie);
4017 return status;
4018 }
4019
4020 status = util_scan_gen_scan_entry(pdev, frame, frame_len,
4021 frm_subtype, rx_param,
4022 &mbssid_info,
4023 scan_list);
4024
4025 if (mbssid_ie)
4026 status = util_scan_parse_mbssid(pdev, frame, frame_len,
4027 frm_subtype, rx_param,
4028 scan_list);
4029
4030 if (QDF_IS_STATUS_ERROR(status))
4031 scm_debug_rl("Failed to create scan entry");
4032
4033 return status;
4034 }
4035
4036 qdf_list_t *
util_scan_unpack_beacon_frame(struct wlan_objmgr_pdev * pdev,uint8_t * frame,qdf_size_t frame_len,uint32_t frm_subtype,struct mgmt_rx_event_params * rx_param)4037 util_scan_unpack_beacon_frame(struct wlan_objmgr_pdev *pdev, uint8_t *frame,
4038 qdf_size_t frame_len, uint32_t frm_subtype,
4039 struct mgmt_rx_event_params *rx_param)
4040 {
4041 qdf_list_t *scan_list;
4042 QDF_STATUS status;
4043
4044 scan_list = qdf_mem_malloc_atomic(sizeof(*scan_list));
4045 if (!scan_list) {
4046 scm_err("failed to allocate scan_list");
4047 return NULL;
4048 }
4049 qdf_list_create(scan_list, MAX_SCAN_CACHE_SIZE);
4050
4051 status = util_scan_parse_beacon_frame(pdev, frame, frame_len,
4052 frm_subtype, rx_param,
4053 scan_list);
4054 if (QDF_IS_STATUS_ERROR(status)) {
4055 ucfg_scan_purge_results(scan_list);
4056 return NULL;
4057 }
4058
4059 return scan_list;
4060 }
4061
4062 QDF_STATUS
util_scan_entry_update_mlme_info(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_entry)4063 util_scan_entry_update_mlme_info(struct wlan_objmgr_pdev *pdev,
4064 struct scan_cache_entry *scan_entry)
4065 {
4066
4067 if (!pdev || !scan_entry) {
4068 scm_err("pdev 0x%pK, scan_entry: 0x%pK", pdev, scan_entry);
4069 return QDF_STATUS_E_INVAL;
4070 }
4071
4072 return scm_update_scan_mlme_info(pdev, scan_entry);
4073 }
4074
util_is_scan_completed(struct scan_event * event,bool * success)4075 bool util_is_scan_completed(struct scan_event *event, bool *success)
4076 {
4077 if ((event->type == SCAN_EVENT_TYPE_COMPLETED) ||
4078 (event->type == SCAN_EVENT_TYPE_DEQUEUED) ||
4079 (event->type == SCAN_EVENT_TYPE_START_FAILED)) {
4080 if ((event->type == SCAN_EVENT_TYPE_COMPLETED) &&
4081 (event->reason == SCAN_REASON_COMPLETED))
4082 *success = true;
4083 else
4084 *success = false;
4085
4086 return true;
4087 }
4088
4089 *success = false;
4090 return false;
4091 }
4092
4093 #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
4094 bool
util_scan_entry_single_pmk(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * scan_entry)4095 util_scan_entry_single_pmk(struct wlan_objmgr_psoc *psoc,
4096 struct scan_cache_entry *scan_entry)
4097 {
4098 if (scan_entry->ie_list.single_pmk &&
4099 wlan_mlme_is_sae_single_pmk_enabled(psoc))
4100 return true;
4101
4102 return false;
4103 }
4104 #endif
4105
util_is_bssid_non_tx(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * bssid,qdf_freq_t freq)4106 bool util_is_bssid_non_tx(struct wlan_objmgr_psoc *psoc,
4107 struct qdf_mac_addr *bssid, qdf_freq_t freq)
4108 {
4109 int i;
4110 qdf_list_node_t *cur_node, *next_node;
4111 struct meta_rnr_channel *channel;
4112 struct scan_rnr_node *rnr_node;
4113 struct channel_list_db *rnr_channel_db;
4114 bool ret = false;
4115
4116 if (!psoc)
4117 return false;
4118
4119 rnr_channel_db = scm_get_rnr_channel_db(psoc);
4120 if (!rnr_channel_db)
4121 return false;
4122
4123 for (i = 0; i < QDF_ARRAY_SIZE(rnr_channel_db->channel); i++) {
4124 channel = &rnr_channel_db->channel[i];
4125 if (channel->chan_freq != freq)
4126 continue;
4127
4128 cur_node = NULL;
4129 qdf_list_peek_front(&channel->rnr_list, &cur_node);
4130
4131 while (cur_node) {
4132 next_node = NULL;
4133 qdf_list_peek_next(&channel->rnr_list, cur_node,
4134 &next_node);
4135 rnr_node = qdf_container_of(cur_node,
4136 struct scan_rnr_node,
4137 node);
4138 if (qdf_is_macaddr_equal(&rnr_node->entry.bssid, bssid) &&
4139 (rnr_node->entry.bss_params &
4140 TBTT_BSS_PARAM_MBSSID_TX_MASK) ==
4141 TBTT_BSS_PARAM_MBSSID_NONTX_MASK) {
4142 ret = true;
4143 break;
4144 }
4145 cur_node = next_node;
4146 }
4147 }
4148
4149 return ret;
4150 }
4151