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