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