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