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