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