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