xref: /wlan-driver/qca-wifi-host-cmn/umac/scan/dispatcher/src/wlan_scan_utils_api.c (revision 5113495b16420b49004c444715d2daae2066e7dc) !
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