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