1 /* 2 * Copyright (c) 2017-2020 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 30 #define MAX_IE_LEN 1024 31 #define SHORT_SSID_LEN 4 32 #define NEIGHBOR_AP_LEN 1 33 #define BSS_PARAMS_LEN 1 34 35 const char* 36 util_scan_get_ev_type_name(enum scan_event_type type) 37 { 38 static const char * const event_name[] = { 39 [SCAN_EVENT_TYPE_STARTED] = "STARTED", 40 [SCAN_EVENT_TYPE_COMPLETED] = "COMPLETED", 41 [SCAN_EVENT_TYPE_BSS_CHANNEL] = "HOME_CHANNEL", 42 [SCAN_EVENT_TYPE_FOREIGN_CHANNEL] = "FOREIGN_CHANNEL", 43 [SCAN_EVENT_TYPE_DEQUEUED] = "DEQUEUED", 44 [SCAN_EVENT_TYPE_PREEMPTED] = "PREEMPTED", 45 [SCAN_EVENT_TYPE_START_FAILED] = "START_FAILED", 46 [SCAN_EVENT_TYPE_RESTARTED] = "RESTARTED", 47 [SCAN_EVENT_TYPE_FOREIGN_CHANNEL_EXIT] = "FOREIGN_CHANNEL_EXIT", 48 [SCAN_EVENT_TYPE_SUSPENDED] = "SUSPENDED", 49 [SCAN_EVENT_TYPE_RESUMED] = "RESUMED", 50 [SCAN_EVENT_TYPE_NLO_COMPLETE] = "NLO_COMPLETE", 51 [SCAN_EVENT_TYPE_NLO_MATCH] = "NLO_MATCH", 52 [SCAN_EVENT_TYPE_INVALID] = "INVALID", 53 [SCAN_EVENT_TYPE_GPIO_TIMEOUT] = "GPIO_TIMEOUT", 54 [SCAN_EVENT_TYPE_RADIO_MEASUREMENT_START] = 55 "RADIO_MEASUREMENT_START", 56 [SCAN_EVENT_TYPE_RADIO_MEASUREMENT_END] = 57 "RADIO_MEASUREMENT_END", 58 [SCAN_EVENT_TYPE_BSSID_MATCH] = "BSSID_MATCH", 59 [SCAN_EVENT_TYPE_FOREIGN_CHANNEL_GET_NF] = 60 "FOREIGN_CHANNEL_GET_NF", 61 }; 62 63 if (type >= SCAN_EVENT_TYPE_MAX) 64 return "UNKNOWN"; 65 66 return event_name[type]; 67 } 68 69 70 const char* 71 util_scan_get_ev_reason_name(enum scan_completion_reason reason) 72 { 73 static const char * const reason_name[] = { 74 [SCAN_REASON_NONE] = "NONE", 75 [SCAN_REASON_COMPLETED] = "COMPLETED", 76 [SCAN_REASON_CANCELLED] = "CANCELLED", 77 [SCAN_REASON_PREEMPTED] = "PREEMPTED", 78 [SCAN_REASON_TIMEDOUT] = "TIMEDOUT", 79 [SCAN_REASON_INTERNAL_FAILURE] = "INTERNAL_FAILURE", 80 [SCAN_REASON_SUSPENDED] = "SUSPENDED", 81 [SCAN_REASON_RUN_FAILED] = "RUN_FAILED", 82 [SCAN_REASON_TERMINATION_FUNCTION] = "TERMINATION_FUNCTION", 83 [SCAN_REASON_MAX_OFFCHAN_RETRIES] = "MAX_OFFCHAN_RETRIES", 84 [SCAN_REASON_DFS_VIOLATION] = "DFS_NOL_VIOLATION", 85 }; 86 87 if (reason >= SCAN_REASON_MAX) 88 return "UNKNOWN"; 89 90 return reason_name[reason]; 91 } 92 93 qdf_time_t 94 util_get_last_scan_time(struct wlan_objmgr_vdev *vdev) 95 { 96 uint8_t pdev_id; 97 struct wlan_scan_obj *scan_obj; 98 99 if (!vdev) { 100 scm_warn("null vdev"); 101 QDF_ASSERT(0); 102 return 0; 103 } 104 pdev_id = wlan_scan_vdev_get_pdev_id(vdev); 105 scan_obj = wlan_vdev_get_scan_obj(vdev); 106 107 if (scan_obj) 108 return scan_obj->pdev_info[pdev_id].last_scan_time; 109 else 110 return 0; 111 } 112 113 enum wlan_band util_scan_scm_chan_to_band(uint32_t chan) 114 { 115 if (WLAN_CHAN_IS_2GHZ(chan)) 116 return WLAN_BAND_2_4_GHZ; 117 118 return WLAN_BAND_5_GHZ; 119 } 120 121 enum wlan_band util_scan_scm_freq_to_band(uint16_t freq) 122 { 123 if (WLAN_REG_IS_24GHZ_CH_FREQ(freq)) 124 return WLAN_BAND_2_4_GHZ; 125 126 return WLAN_BAND_5_GHZ; 127 } 128 129 bool util_is_scan_entry_match( 130 struct scan_cache_entry *entry1, 131 struct scan_cache_entry *entry2) 132 { 133 134 if (entry1->cap_info.wlan_caps.ess != 135 entry2->cap_info.wlan_caps.ess) 136 return false; 137 138 if (entry1->cap_info.wlan_caps.ess && 139 !qdf_mem_cmp(entry1->bssid.bytes, 140 entry2->bssid.bytes, QDF_MAC_ADDR_SIZE)) { 141 /* Check for BSS */ 142 if (util_is_ssid_match(&entry1->ssid, &entry2->ssid) || 143 util_scan_is_null_ssid(&entry1->ssid) || 144 util_scan_is_null_ssid(&entry2->ssid)) 145 return true; 146 } else if (entry1->cap_info.wlan_caps.ibss && 147 (entry1->channel.chan_freq == 148 entry2->channel.chan_freq)) { 149 /* 150 * Same channel cannot have same SSID for 151 * different IBSS, so no need to check BSSID 152 */ 153 if (util_is_ssid_match( 154 &entry1->ssid, &entry2->ssid)) 155 return true; 156 } else if (!entry1->cap_info.wlan_caps.ibss && 157 !entry1->cap_info.wlan_caps.ess && 158 !qdf_mem_cmp(entry1->bssid.bytes, 159 entry2->bssid.bytes, QDF_MAC_ADDR_SIZE)) { 160 /* In case of P2P devices, ess and ibss will be set to zero */ 161 return true; 162 } 163 164 return false; 165 } 166 167 static bool util_is_pureg_rate(uint8_t *rates, uint8_t nrates) 168 { 169 static const uint8_t g_rates[] = {12, 18, 24, 36, 48, 72, 96, 108}; 170 bool pureg = false; 171 uint8_t i, j; 172 173 for (i = 0; i < nrates; i++) { 174 for (j = 0; j < QDF_ARRAY_SIZE(g_rates); j++) { 175 if (WLAN_RV(rates[i]) == g_rates[j]) { 176 pureg = true; 177 break; 178 } 179 } 180 if (pureg) 181 break; 182 } 183 184 return pureg; 185 } 186 187 #ifdef CONFIG_BAND_6GHZ 188 static struct he_oper_6g_param *util_scan_get_he_6g_params(uint8_t *he_ops) 189 { 190 uint8_t len; 191 uint32_t he_oper_params; 192 193 if (!he_ops) 194 return NULL; 195 196 len = he_ops[1]; 197 he_ops += sizeof(struct ie_header); 198 199 if (len < WLAN_HEOP_FIXED_PARAM_LENGTH) 200 return NULL; 201 202 /* element id extension */ 203 he_ops++; 204 len--; 205 206 he_oper_params = LE_READ_4(he_ops); 207 if (!(he_oper_params & WLAN_HEOP_6GHZ_INFO_PRESENT_MASK)) 208 return NULL; 209 210 /* fixed params - element id extension */ 211 he_ops += WLAN_HEOP_FIXED_PARAM_LENGTH - 1; 212 len -= WLAN_HEOP_FIXED_PARAM_LENGTH - 1; 213 214 if (!len) 215 return NULL; 216 217 /* vht oper params */ 218 if (he_oper_params & WLAN_HEOP_VHTOP_PRESENT_MASK) { 219 if (len < WLAN_HEOP_VHTOP_LENGTH) 220 return NULL; 221 he_ops += WLAN_HEOP_VHTOP_LENGTH; 222 len -= WLAN_HEOP_VHTOP_LENGTH; 223 } 224 225 if (!len) 226 return NULL; 227 228 if (he_oper_params & WLAN_HEOP_CO_LOCATED_BSS_MASK) { 229 he_ops += WLAN_HEOP_CO_LOCATED_BSS_LENGTH; 230 len -= WLAN_HEOP_CO_LOCATED_BSS_LENGTH; 231 } 232 233 if (len < sizeof(struct he_oper_6g_param)) 234 return NULL; 235 236 return (struct he_oper_6g_param *)he_ops; 237 } 238 239 static void 240 util_scan_get_chan_from_he_6g_params(struct scan_cache_entry *scan_params, 241 uint8_t *chan_idx) 242 { 243 struct he_oper_6g_param *he_6g_params; 244 uint8_t *he_ops; 245 246 he_ops = util_scan_entry_heop(scan_params); 247 if (!util_scan_entry_hecap(scan_params) || !he_ops) 248 return; 249 250 he_6g_params = util_scan_get_he_6g_params(he_ops); 251 if (!he_6g_params) 252 return; 253 254 *chan_idx = he_6g_params->primary_channel; 255 } 256 257 static enum wlan_phymode 258 util_scan_get_phymode_6g(struct wlan_objmgr_pdev *pdev, 259 struct scan_cache_entry *scan_params) 260 { 261 struct he_oper_6g_param *he_6g_params; 262 enum wlan_phymode phymode = WLAN_PHYMODE_11AXA_HE20; 263 uint8_t *he_ops; 264 uint8_t band_mask = BIT(REG_BAND_6G); 265 266 he_ops = util_scan_entry_heop(scan_params); 267 if (!util_scan_entry_hecap(scan_params) || !he_ops) 268 return phymode; 269 270 he_6g_params = util_scan_get_he_6g_params(he_ops); 271 if (!he_6g_params) 272 return phymode; 273 274 switch (he_6g_params->width) { 275 case WLAN_HE_6GHZ_CHWIDTH_20: 276 phymode = WLAN_PHYMODE_11AXA_HE20; 277 break; 278 case WLAN_HE_6GHZ_CHWIDTH_40: 279 phymode = WLAN_PHYMODE_11AXA_HE40; 280 break; 281 case WLAN_HE_6GHZ_CHWIDTH_80: 282 phymode = WLAN_PHYMODE_11AXA_HE80; 283 break; 284 case WLAN_HE_6GHZ_CHWIDTH_160_80_80: 285 if (WLAN_IS_HE80_80(he_6g_params)) 286 phymode = WLAN_PHYMODE_11AXA_HE80_80; 287 else if (WLAN_IS_HE160(he_6g_params)) 288 phymode = WLAN_PHYMODE_11AXA_HE160; 289 else 290 phymode = WLAN_PHYMODE_11AXA_HE80; 291 break; 292 default: 293 scm_err("Invalid he_6g_params width: %d", he_6g_params->width); 294 phymode = WLAN_PHYMODE_11AXA_HE20; 295 break; 296 } 297 298 if (he_6g_params->chan_freq_seg0) 299 scan_params->channel.cfreq0 = 300 wlan_reg_chan_band_to_freq(pdev, 301 he_6g_params->chan_freq_seg0, 302 band_mask); 303 if (he_6g_params->chan_freq_seg1) 304 scan_params->channel.cfreq1 = 305 wlan_reg_chan_band_to_freq(pdev, 306 he_6g_params->chan_freq_seg1, 307 band_mask); 308 309 return phymode; 310 } 311 #else 312 static void 313 util_scan_get_chan_from_he_6g_params(struct scan_cache_entry *scan_params, 314 uint8_t *chan_idx) 315 {} 316 static inline enum wlan_phymode 317 util_scan_get_phymode_6g(struct wlan_objmgr_pdev *pdev, 318 struct scan_cache_entry *scan_params) 319 { 320 return WLAN_PHYMODE_AUTO; 321 } 322 #endif 323 324 static inline 325 uint32_t util_scan_sec_chan_freq_from_htinfo(struct wlan_ie_htinfo_cmn *htinfo, 326 uint32_t primary_chan_freq) 327 { 328 if (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_ABOVE) 329 return primary_chan_freq + WLAN_CHAN_SPACING_20MHZ; 330 else if (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_BELOW) 331 return primary_chan_freq - WLAN_CHAN_SPACING_20MHZ; 332 333 return 0; 334 } 335 336 static enum wlan_phymode 337 util_scan_get_phymode_5g(struct wlan_objmgr_pdev *pdev, 338 struct scan_cache_entry *scan_params) 339 { 340 enum wlan_phymode phymode = WLAN_PHYMODE_AUTO; 341 uint16_t ht_cap = 0; 342 struct htcap_cmn_ie *htcap; 343 struct wlan_ie_htinfo_cmn *htinfo; 344 struct wlan_ie_vhtop *vhtop; 345 uint8_t band_mask = BIT(REG_BAND_5G); 346 347 htcap = (struct htcap_cmn_ie *) 348 util_scan_entry_htcap(scan_params); 349 htinfo = (struct wlan_ie_htinfo_cmn *) 350 util_scan_entry_htinfo(scan_params); 351 vhtop = (struct wlan_ie_vhtop *) 352 util_scan_entry_vhtop(scan_params); 353 354 if (!(htcap && htinfo)) 355 return WLAN_PHYMODE_11A; 356 357 if (htcap) 358 ht_cap = le16toh(htcap->hc_cap); 359 360 if (ht_cap & WLAN_HTCAP_C_CHWIDTH40) 361 phymode = WLAN_PHYMODE_11NA_HT40; 362 else 363 phymode = WLAN_PHYMODE_11NA_HT20; 364 365 scan_params->channel.cfreq0 = 366 util_scan_sec_chan_freq_from_htinfo(htinfo, 367 scan_params->channel.chan_freq); 368 369 if (util_scan_entry_vhtcap(scan_params) && vhtop) { 370 switch (vhtop->vht_op_chwidth) { 371 case WLAN_VHTOP_CHWIDTH_2040: 372 if (ht_cap & WLAN_HTCAP_C_CHWIDTH40) 373 phymode = WLAN_PHYMODE_11AC_VHT40; 374 else 375 phymode = WLAN_PHYMODE_11AC_VHT20; 376 break; 377 case WLAN_VHTOP_CHWIDTH_80: 378 if (WLAN_IS_REVSIG_VHT80_80(vhtop)) 379 phymode = WLAN_PHYMODE_11AC_VHT80_80; 380 else if (WLAN_IS_REVSIG_VHT160(vhtop)) 381 phymode = WLAN_PHYMODE_11AC_VHT160; 382 else 383 phymode = WLAN_PHYMODE_11AC_VHT80; 384 break; 385 case WLAN_VHTOP_CHWIDTH_160: 386 phymode = WLAN_PHYMODE_11AC_VHT160; 387 break; 388 case WLAN_VHTOP_CHWIDTH_80_80: 389 phymode = WLAN_PHYMODE_11AC_VHT80_80; 390 break; 391 default: 392 scm_err("bad channel: %d", 393 vhtop->vht_op_chwidth); 394 phymode = WLAN_PHYMODE_11AC_VHT20; 395 break; 396 } 397 if (vhtop->vht_op_ch_freq_seg1) 398 scan_params->channel.cfreq0 = 399 wlan_reg_chan_band_to_freq(pdev, 400 vhtop->vht_op_ch_freq_seg1, 401 band_mask); 402 if (vhtop->vht_op_ch_freq_seg2) 403 scan_params->channel.cfreq1 = 404 wlan_reg_chan_band_to_freq(pdev, 405 vhtop->vht_op_ch_freq_seg2, 406 band_mask); 407 } 408 409 if (!util_scan_entry_hecap(scan_params)) 410 return phymode; 411 412 /* for 5Ghz Check for HE, only if VHT cap and HE cap are present */ 413 if (!IS_WLAN_PHYMODE_VHT(phymode)) 414 return phymode; 415 416 switch (phymode) { 417 case WLAN_PHYMODE_11AC_VHT20: 418 phymode = WLAN_PHYMODE_11AXA_HE20; 419 break; 420 case WLAN_PHYMODE_11AC_VHT40: 421 phymode = WLAN_PHYMODE_11AXA_HE40; 422 break; 423 case WLAN_PHYMODE_11AC_VHT80: 424 phymode = WLAN_PHYMODE_11AXA_HE80; 425 break; 426 case WLAN_PHYMODE_11AC_VHT160: 427 phymode = WLAN_PHYMODE_11AXA_HE160; 428 break; 429 case WLAN_PHYMODE_11AC_VHT80_80: 430 phymode = WLAN_PHYMODE_11AXA_HE80_80; 431 break; 432 default: 433 phymode = WLAN_PHYMODE_11AXA_HE20; 434 break; 435 } 436 437 return phymode; 438 } 439 440 static enum wlan_phymode 441 util_scan_get_phymode_2g(struct scan_cache_entry *scan_params) 442 { 443 enum wlan_phymode phymode = WLAN_PHYMODE_AUTO; 444 uint16_t ht_cap = 0; 445 struct htcap_cmn_ie *htcap; 446 struct wlan_ie_htinfo_cmn *htinfo; 447 struct wlan_ie_vhtop *vhtop; 448 449 htcap = (struct htcap_cmn_ie *) 450 util_scan_entry_htcap(scan_params); 451 htinfo = (struct wlan_ie_htinfo_cmn *) 452 util_scan_entry_htinfo(scan_params); 453 vhtop = (struct wlan_ie_vhtop *) 454 util_scan_entry_vhtop(scan_params); 455 456 if (htcap) 457 ht_cap = le16toh(htcap->hc_cap); 458 459 if (htcap && htinfo) { 460 if ((ht_cap & WLAN_HTCAP_C_CHWIDTH40) && 461 (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_ABOVE)) 462 phymode = WLAN_PHYMODE_11NG_HT40PLUS; 463 else if ((ht_cap & WLAN_HTCAP_C_CHWIDTH40) && 464 (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_BELOW)) 465 phymode = WLAN_PHYMODE_11NG_HT40MINUS; 466 else 467 phymode = WLAN_PHYMODE_11NG_HT20; 468 } else if (util_scan_entry_xrates(scan_params)) { 469 /* only 11G stations will have more than 8 rates */ 470 phymode = WLAN_PHYMODE_11G; 471 } else { 472 /* Some mischievous g-only APs do not set extended rates */ 473 if (util_scan_entry_rates(scan_params)) { 474 if (util_is_pureg_rate(&scan_params->ie_list.rates[2], 475 scan_params->ie_list.rates[1])) 476 phymode = WLAN_PHYMODE_11G; 477 else 478 phymode = WLAN_PHYMODE_11B; 479 } else { 480 phymode = WLAN_PHYMODE_11B; 481 } 482 } 483 484 /* Check for VHT only if HT cap is present */ 485 if (!IS_WLAN_PHYMODE_HT(phymode)) 486 return phymode; 487 488 scan_params->channel.cfreq0 = 489 util_scan_sec_chan_freq_from_htinfo(htinfo, 490 scan_params->channel.chan_freq); 491 492 if (util_scan_entry_vhtcap(scan_params) && vhtop) { 493 switch (vhtop->vht_op_chwidth) { 494 case WLAN_VHTOP_CHWIDTH_2040: 495 if (phymode == WLAN_PHYMODE_11NG_HT40PLUS) 496 phymode = WLAN_PHYMODE_11AC_VHT40PLUS_2G; 497 else if (phymode == WLAN_PHYMODE_11NG_HT40MINUS) 498 phymode = WLAN_PHYMODE_11AC_VHT40MINUS_2G; 499 else 500 phymode = WLAN_PHYMODE_11AC_VHT20_2G; 501 502 break; 503 default: 504 scm_info("bad vht_op_chwidth: %d", 505 vhtop->vht_op_chwidth); 506 phymode = WLAN_PHYMODE_11AC_VHT20_2G; 507 break; 508 } 509 } 510 511 if (!util_scan_entry_hecap(scan_params)) 512 return phymode; 513 514 if (phymode == WLAN_PHYMODE_11AC_VHT40PLUS_2G || 515 phymode == WLAN_PHYMODE_11NG_HT40PLUS) 516 phymode = WLAN_PHYMODE_11AXG_HE40PLUS; 517 else if (phymode == WLAN_PHYMODE_11AC_VHT40MINUS_2G || 518 phymode == WLAN_PHYMODE_11NG_HT40MINUS) 519 phymode = WLAN_PHYMODE_11AXG_HE40MINUS; 520 else 521 phymode = WLAN_PHYMODE_11AXG_HE20; 522 523 return phymode; 524 } 525 526 static enum wlan_phymode 527 util_scan_get_phymode(struct wlan_objmgr_pdev *pdev, 528 struct scan_cache_entry *scan_params) 529 { 530 if (WLAN_REG_IS_24GHZ_CH_FREQ(scan_params->channel.chan_freq)) 531 return util_scan_get_phymode_2g(scan_params); 532 else if (WLAN_REG_IS_6GHZ_CHAN_FREQ(scan_params->channel.chan_freq)) 533 return util_scan_get_phymode_6g(pdev, scan_params); 534 else 535 return util_scan_get_phymode_5g(pdev, scan_params); 536 } 537 538 static QDF_STATUS 539 util_scan_parse_chan_switch_wrapper_ie(struct scan_cache_entry *scan_params, 540 struct ie_header *sub_ie, qdf_size_t sub_ie_len) 541 { 542 /* Walk through to check nothing is malformed */ 543 while (sub_ie_len >= sizeof(struct ie_header)) { 544 /* At least one more header is present */ 545 sub_ie_len -= sizeof(struct ie_header); 546 547 if (sub_ie->ie_len == 0) { 548 sub_ie += 1; 549 continue; 550 } 551 if (sub_ie_len < sub_ie->ie_len) { 552 scm_err("Incomplete corrupted IE:%x", 553 WLAN_ELEMID_CHAN_SWITCH_WRAP); 554 return QDF_STATUS_E_INVAL; 555 } 556 switch (sub_ie->ie_id) { 557 case WLAN_ELEMID_COUNTRY: 558 scan_params->ie_list.country = (uint8_t *)sub_ie; 559 break; 560 case WLAN_ELEMID_WIDE_BAND_CHAN_SWITCH: 561 scan_params->ie_list.widebw = (uint8_t *)sub_ie; 562 break; 563 case WLAN_ELEMID_VHT_TX_PWR_ENVLP: 564 scan_params->ie_list.txpwrenvlp = (uint8_t *)sub_ie; 565 break; 566 } 567 /* Consume sub info element */ 568 sub_ie_len -= sub_ie->ie_len; 569 /* go to next Sub IE */ 570 sub_ie = (struct ie_header *) 571 (((uint8_t *) sub_ie) + 572 sizeof(struct ie_header) + sub_ie->ie_len); 573 } 574 575 return QDF_STATUS_SUCCESS; 576 } 577 578 bool 579 util_scan_is_hidden_ssid(struct ie_ssid *ssid) 580 { 581 uint8_t i; 582 583 /* 584 * We flag this as Hidden SSID if the Length is 0 585 * of the SSID only contains 0's 586 */ 587 if (!ssid || !ssid->ssid_len) 588 return true; 589 590 for (i = 0; i < ssid->ssid_len; i++) 591 if (ssid->ssid[i] != 0) 592 return false; 593 594 /* All 0's */ 595 return true; 596 } 597 598 static QDF_STATUS 599 util_scan_update_rnr(struct rnr_bss_info *rnr, 600 struct neighbor_ap_info_field *ap_info, 601 uint8_t *data) 602 { 603 uint8_t tbtt_info_length; 604 605 tbtt_info_length = ap_info->tbtt_header.tbtt_info_length; 606 607 switch (tbtt_info_length) { 608 case TBTT_NEIGHBOR_AP_OFFSET_ONLY: 609 /* Dont store it skip*/ 610 break; 611 612 case TBTT_NEIGHBOR_AP_BSS_PARAM: 613 /* Dont store it skip*/ 614 break; 615 616 case TBTT_NEIGHBOR_AP_SHORTSSID: 617 rnr->channel_number = ap_info->channel_number; 618 rnr->operating_class = ap_info->operting_class; 619 qdf_mem_copy(&rnr->short_ssid, &data[1], SHORT_SSID_LEN); 620 break; 621 622 case TBTT_NEIGHBOR_AP_S_SSID_BSS_PARAM: 623 rnr->channel_number = ap_info->channel_number; 624 rnr->operating_class = ap_info->operting_class; 625 qdf_mem_copy(&rnr->short_ssid, &data[1], SHORT_SSID_LEN); 626 rnr->bss_params = data[5]; 627 break; 628 629 case TBTT_NEIGHBOR_AP_BSSID: 630 rnr->channel_number = ap_info->channel_number; 631 rnr->operating_class = ap_info->operting_class; 632 qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE); 633 break; 634 635 case TBTT_NEIGHBOR_AP_BSSID_BSS_PARAM: 636 rnr->channel_number = ap_info->channel_number; 637 rnr->operating_class = ap_info->operting_class; 638 qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE); 639 rnr->bss_params = data[7]; 640 break; 641 642 case TBTT_NEIGHBOR_AP_BSSSID_S_SSID: 643 rnr->channel_number = ap_info->channel_number; 644 rnr->operating_class = ap_info->operting_class; 645 qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE); 646 qdf_mem_copy(&rnr->short_ssid, &data[7], SHORT_SSID_LEN); 647 break; 648 649 case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM: 650 rnr->channel_number = ap_info->channel_number; 651 rnr->operating_class = ap_info->operting_class; 652 qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE); 653 qdf_mem_copy(&rnr->short_ssid, &data[7], SHORT_SSID_LEN); 654 rnr->bss_params = data[11]; 655 break; 656 657 default: 658 scm_debug("Wrong fieldtype"); 659 } 660 661 return QDF_STATUS_SUCCESS; 662 } 663 664 static QDF_STATUS 665 util_scan_parse_rnr_ie(struct scan_cache_entry *scan_entry, 666 struct ie_header *ie) 667 { 668 uint32_t rnr_ie_len; 669 uint16_t tbtt_count, tbtt_length, i, fieldtype; 670 uint8_t *data; 671 struct neighbor_ap_info_field *neighbor_ap_info; 672 673 rnr_ie_len = ie->ie_len; 674 data = (uint8_t *)ie + sizeof(struct ie_header); 675 676 while (data < ((uint8_t *)ie + rnr_ie_len + 2)) { 677 neighbor_ap_info = (struct neighbor_ap_info_field *)data; 678 tbtt_count = neighbor_ap_info->tbtt_header.tbtt_info_count; 679 tbtt_length = neighbor_ap_info->tbtt_header.tbtt_info_length; 680 fieldtype = neighbor_ap_info->tbtt_header.tbbt_info_fieldtype; 681 scm_debug("channel number %d, op class %d", 682 neighbor_ap_info->channel_number, 683 neighbor_ap_info->operting_class); 684 scm_debug("tbtt_count %d, tbtt_length %d, fieldtype %d", 685 tbtt_count, tbtt_length, fieldtype); 686 data += sizeof(struct neighbor_ap_info_field); 687 for (i = 0; i < (tbtt_count + 1) ; i++) { 688 if (i < MAX_RNR_BSS) 689 util_scan_update_rnr( 690 &scan_entry->rnr.bss_info[i], 691 neighbor_ap_info, 692 data); 693 data += tbtt_length; 694 } 695 } 696 697 return QDF_STATUS_SUCCESS; 698 } 699 700 static QDF_STATUS 701 util_scan_parse_extn_ie(struct scan_cache_entry *scan_params, 702 struct ie_header *ie) 703 { 704 struct extn_ie_header *extn_ie = (struct extn_ie_header *) ie; 705 706 switch (extn_ie->ie_extn_id) { 707 case WLAN_EXTN_ELEMID_MAX_CHAN_SWITCH_TIME: 708 scan_params->ie_list.mcst = (uint8_t *)ie; 709 break; 710 case WLAN_EXTN_ELEMID_SRP: 711 scan_params->ie_list.srp = (uint8_t *)ie; 712 break; 713 case WLAN_EXTN_ELEMID_HECAP: 714 scan_params->ie_list.hecap = (uint8_t *)ie; 715 break; 716 case WLAN_EXTN_ELEMID_HEOP: 717 scan_params->ie_list.heop = (uint8_t *)ie; 718 break; 719 case WLAN_EXTN_ELEMID_ESP: 720 scan_params->ie_list.esp = (uint8_t *)ie; 721 break; 722 case WLAN_EXTN_ELEMID_MUEDCA: 723 scan_params->ie_list.muedca = (uint8_t *)ie; 724 break; 725 case WLAN_EXTN_ELEMID_HE_6G_CAP: 726 scan_params->ie_list.hecap_6g = (uint8_t *)ie; 727 break; 728 default: 729 break; 730 } 731 return QDF_STATUS_SUCCESS; 732 } 733 734 static QDF_STATUS 735 util_scan_parse_vendor_ie(struct scan_cache_entry *scan_params, 736 struct ie_header *ie) 737 { 738 if (!scan_params->ie_list.vendor) 739 scan_params->ie_list.vendor = (uint8_t *)ie; 740 741 if (is_wpa_oui((uint8_t *)ie)) { 742 scan_params->ie_list.wpa = (uint8_t *)ie; 743 } else if (is_wps_oui((uint8_t *)ie)) { 744 scan_params->ie_list.wps = (uint8_t *)ie; 745 /* WCN IE should be a subset of WPS IE */ 746 if (is_wcn_oui((uint8_t *)ie)) 747 scan_params->ie_list.wcn = (uint8_t *)ie; 748 } else if (is_wme_param((uint8_t *)ie)) { 749 scan_params->ie_list.wmeparam = (uint8_t *)ie; 750 } else if (is_wme_info((uint8_t *)ie)) { 751 scan_params->ie_list.wmeinfo = (uint8_t *)ie; 752 } else if (is_atheros_oui((uint8_t *)ie)) { 753 scan_params->ie_list.athcaps = (uint8_t *)ie; 754 } else if (is_atheros_extcap_oui((uint8_t *)ie)) { 755 scan_params->ie_list.athextcaps = (uint8_t *)ie; 756 } else if (is_sfa_oui((uint8_t *)ie)) { 757 scan_params->ie_list.sfa = (uint8_t *)ie; 758 } else if (is_p2p_oui((uint8_t *)ie)) { 759 scan_params->ie_list.p2p = (uint8_t *)ie; 760 } else if (is_qca_son_oui((uint8_t *)ie, 761 QCA_OUI_WHC_AP_INFO_SUBTYPE)) { 762 scan_params->ie_list.sonadv = (uint8_t *)ie; 763 } else if (is_ht_cap((uint8_t *)ie)) { 764 /* we only care if there isn't already an HT IE (ANA) */ 765 if (!scan_params->ie_list.htcap) { 766 if (ie->ie_len != (WLAN_VENDOR_HT_IE_OFFSET_LEN + 767 sizeof(struct htcap_cmn_ie))) 768 return QDF_STATUS_E_INVAL; 769 scan_params->ie_list.htcap = 770 (uint8_t *)&(((struct wlan_vendor_ie_htcap *)ie)->ie); 771 } 772 } else if (is_ht_info((uint8_t *)ie)) { 773 /* we only care if there isn't already an HT IE (ANA) */ 774 if (!scan_params->ie_list.htinfo) { 775 if (ie->ie_len != WLAN_VENDOR_HT_IE_OFFSET_LEN + 776 sizeof(struct wlan_ie_htinfo_cmn)) 777 return QDF_STATUS_E_INVAL; 778 scan_params->ie_list.htinfo = 779 (uint8_t *)&(((struct wlan_vendor_ie_htinfo *) 780 ie)->hi_ie); 781 } 782 } else if (is_interop_vht((uint8_t *)ie) && 783 !(scan_params->ie_list.vhtcap)) { 784 uint8_t *vendor_ie = (uint8_t *)(ie); 785 786 if (ie->ie_len < ((WLAN_VENDOR_VHTCAP_IE_OFFSET + 787 sizeof(struct wlan_ie_vhtcaps)) - 788 sizeof(struct ie_header))) 789 return QDF_STATUS_E_INVAL; 790 vendor_ie = ((uint8_t *)(ie)) + WLAN_VENDOR_VHTCAP_IE_OFFSET; 791 if (vendor_ie[1] != (sizeof(struct wlan_ie_vhtcaps)) - 792 sizeof(struct ie_header)) 793 return QDF_STATUS_E_INVAL; 794 /* location where Interop Vht Cap IE and VHT OP IE Present */ 795 scan_params->ie_list.vhtcap = (((uint8_t *)(ie)) + 796 WLAN_VENDOR_VHTCAP_IE_OFFSET); 797 if (ie->ie_len > ((WLAN_VENDOR_VHTCAP_IE_OFFSET + 798 sizeof(struct wlan_ie_vhtcaps)) - 799 sizeof(struct ie_header))) { 800 if (ie->ie_len < ((WLAN_VENDOR_VHTOP_IE_OFFSET + 801 sizeof(struct wlan_ie_vhtop)) - 802 sizeof(struct ie_header))) 803 return QDF_STATUS_E_INVAL; 804 vendor_ie = ((uint8_t *)(ie)) + 805 WLAN_VENDOR_VHTOP_IE_OFFSET; 806 if (vendor_ie[1] != (sizeof(struct wlan_ie_vhtop) - 807 sizeof(struct ie_header))) 808 return QDF_STATUS_E_INVAL; 809 scan_params->ie_list.vhtop = (((uint8_t *)(ie)) + 810 WLAN_VENDOR_VHTOP_IE_OFFSET); 811 } 812 } else if (is_bwnss_oui((uint8_t *)ie)) { 813 /* 814 * Bandwidth-NSS map has sub-type & version. 815 * hence copy data just after version byte 816 */ 817 scan_params->ie_list.bwnss_map = (((uint8_t *)ie) + 8); 818 } else if (is_mbo_oce_oui((uint8_t *)ie)) { 819 scan_params->ie_list.mbo_oce = (uint8_t *)ie; 820 } else if (is_extender_oui((uint8_t *)ie)) { 821 scan_params->ie_list.extender = (uint8_t *)ie; 822 } else if (is_adaptive_11r_oui((uint8_t *)ie)) { 823 if ((ie->ie_len < OUI_LENGTH) || 824 (ie->ie_len > MAX_ADAPTIVE_11R_IE_LEN)) 825 return QDF_STATUS_E_INVAL; 826 827 scan_params->ie_list.adaptive_11r = (uint8_t *)ie + 828 sizeof(struct ie_header); 829 } 830 return QDF_STATUS_SUCCESS; 831 } 832 833 static QDF_STATUS 834 util_scan_populate_bcn_ie_list(struct scan_cache_entry *scan_params, 835 uint8_t *chan_idx) 836 { 837 struct ie_header *ie, *sub_ie; 838 uint32_t ie_len, sub_ie_len; 839 QDF_STATUS status; 840 841 ie_len = util_scan_entry_ie_len(scan_params); 842 ie = (struct ie_header *) 843 util_scan_entry_ie_data(scan_params); 844 845 while (ie_len >= sizeof(struct ie_header)) { 846 ie_len -= sizeof(struct ie_header); 847 848 if (!ie->ie_len) { 849 ie += 1; 850 continue; 851 } 852 853 if (ie_len < ie->ie_len) { 854 scm_debug("Incomplete corrupted IE:%x", 855 ie->ie_id); 856 return QDF_STATUS_E_INVAL; 857 } 858 859 switch (ie->ie_id) { 860 case WLAN_ELEMID_SSID: 861 if (ie->ie_len > (sizeof(struct ie_ssid) - 862 sizeof(struct ie_header))) 863 goto err; 864 scan_params->ie_list.ssid = (uint8_t *)ie; 865 break; 866 case WLAN_ELEMID_RATES: 867 if (ie->ie_len > WLAN_SUPPORTED_RATES_IE_MAX_LEN) 868 goto err; 869 scan_params->ie_list.rates = (uint8_t *)ie; 870 break; 871 case WLAN_ELEMID_DSPARMS: 872 if (ie->ie_len != WLAN_DS_PARAM_IE_MAX_LEN) 873 return QDF_STATUS_E_INVAL; 874 scan_params->ie_list.ds_param = (uint8_t *)ie; 875 *chan_idx = 876 ((struct ds_ie *)ie)->cur_chan; 877 break; 878 case WLAN_ELEMID_TIM: 879 if (ie->ie_len < WLAN_TIM_IE_MIN_LENGTH) 880 goto err; 881 scan_params->ie_list.tim = (uint8_t *)ie; 882 scan_params->dtim_period = 883 ((struct wlan_tim_ie *)ie)->tim_period; 884 break; 885 case WLAN_ELEMID_COUNTRY: 886 if (ie->ie_len < WLAN_COUNTRY_IE_MIN_LEN) 887 goto err; 888 scan_params->ie_list.country = (uint8_t *)ie; 889 break; 890 case WLAN_ELEMID_QBSS_LOAD: 891 if (ie->ie_len != sizeof(struct qbss_load_ie) - 892 sizeof(struct ie_header)) { 893 /* 894 * Expected QBSS IE length is 5Bytes; For some 895 * old cisco AP, QBSS IE length is 4Bytes, which 896 * doesn't match with latest spec, So ignore 897 * QBSS IE in such case. 898 */ 899 break; 900 } 901 scan_params->ie_list.qbssload = (uint8_t *)ie; 902 break; 903 case WLAN_ELEMID_CHANSWITCHANN: 904 if (ie->ie_len != WLAN_CSA_IE_MAX_LEN) 905 goto err; 906 scan_params->ie_list.csa = (uint8_t *)ie; 907 break; 908 case WLAN_ELEMID_IBSSDFS: 909 if (ie->ie_len < WLAN_IBSSDFS_IE_MIN_LEN) 910 goto err; 911 scan_params->ie_list.ibssdfs = (uint8_t *)ie; 912 break; 913 case WLAN_ELEMID_QUIET: 914 if (ie->ie_len != WLAN_QUIET_IE_MAX_LEN) 915 goto err; 916 scan_params->ie_list.quiet = (uint8_t *)ie; 917 break; 918 case WLAN_ELEMID_ERP: 919 if (ie->ie_len != (sizeof(struct erp_ie) - 920 sizeof(struct ie_header))) 921 goto err; 922 scan_params->erp = ((struct erp_ie *)ie)->value; 923 break; 924 case WLAN_ELEMID_HTCAP_ANA: 925 if (ie->ie_len != sizeof(struct htcap_cmn_ie)) 926 goto err; 927 scan_params->ie_list.htcap = 928 (uint8_t *)&(((struct htcap_ie *)ie)->ie); 929 break; 930 case WLAN_ELEMID_RSN: 931 if (ie->ie_len < WLAN_RSN_IE_MIN_LEN) 932 goto err; 933 scan_params->ie_list.rsn = (uint8_t *)ie; 934 break; 935 case WLAN_ELEMID_XRATES: 936 scan_params->ie_list.xrates = (uint8_t *)ie; 937 break; 938 case WLAN_ELEMID_EXTCHANSWITCHANN: 939 if (ie->ie_len != WLAN_XCSA_IE_MAX_LEN) 940 goto err; 941 scan_params->ie_list.xcsa = (uint8_t *)ie; 942 break; 943 case WLAN_ELEMID_SECCHANOFFSET: 944 if (ie->ie_len != WLAN_SECCHANOFF_IE_MAX_LEN) 945 goto err; 946 scan_params->ie_list.secchanoff = (uint8_t *)ie; 947 break; 948 case WLAN_ELEMID_HTINFO_ANA: 949 if (ie->ie_len != sizeof(struct wlan_ie_htinfo_cmn)) 950 goto err; 951 scan_params->ie_list.htinfo = 952 (uint8_t *)&(((struct wlan_ie_htinfo *) ie)->hi_ie); 953 *chan_idx = 954 ((struct wlan_ie_htinfo_cmn *) 955 (scan_params->ie_list.htinfo))->hi_ctrlchannel; 956 break; 957 case WLAN_ELEMID_WAPI: 958 if (ie->ie_len < WLAN_WAPI_IE_MIN_LEN) 959 goto err; 960 scan_params->ie_list.wapi = (uint8_t *)ie; 961 break; 962 case WLAN_ELEMID_XCAPS: 963 if (ie->ie_len > WLAN_EXTCAP_IE_MAX_LEN) 964 goto err; 965 scan_params->ie_list.extcaps = (uint8_t *)ie; 966 break; 967 case WLAN_ELEMID_VHTCAP: 968 if (ie->ie_len != (sizeof(struct wlan_ie_vhtcaps) - 969 sizeof(struct ie_header))) 970 goto err; 971 scan_params->ie_list.vhtcap = (uint8_t *)ie; 972 break; 973 case WLAN_ELEMID_VHTOP: 974 if (ie->ie_len != (sizeof(struct wlan_ie_vhtop) - 975 sizeof(struct ie_header))) 976 goto err; 977 scan_params->ie_list.vhtop = (uint8_t *)ie; 978 break; 979 case WLAN_ELEMID_OP_MODE_NOTIFY: 980 if (ie->ie_len != WLAN_OPMODE_IE_MAX_LEN) 981 goto err; 982 scan_params->ie_list.opmode = (uint8_t *)ie; 983 break; 984 case WLAN_ELEMID_MOBILITY_DOMAIN: 985 if (ie->ie_len != WLAN_MOBILITY_DOMAIN_IE_MAX_LEN) 986 goto err; 987 scan_params->ie_list.mdie = (uint8_t *)ie; 988 break; 989 case WLAN_ELEMID_VENDOR: 990 status = util_scan_parse_vendor_ie(scan_params, 991 ie); 992 if (QDF_IS_STATUS_ERROR(status)) 993 goto err_status; 994 break; 995 case WLAN_ELEMID_CHAN_SWITCH_WRAP: 996 scan_params->ie_list.cswrp = (uint8_t *)ie; 997 /* Go to next sub IE */ 998 sub_ie = (struct ie_header *) 999 (((uint8_t *)ie) + sizeof(struct ie_header)); 1000 sub_ie_len = ie->ie_len; 1001 status = 1002 util_scan_parse_chan_switch_wrapper_ie( 1003 scan_params, sub_ie, sub_ie_len); 1004 if (QDF_IS_STATUS_ERROR(status)) { 1005 goto err_status; 1006 } 1007 break; 1008 case WLAN_ELEMID_FILS_INDICATION: 1009 if (ie->ie_len < WLAN_FILS_INDICATION_IE_MIN_LEN) 1010 goto err; 1011 scan_params->ie_list.fils_indication = (uint8_t *)ie; 1012 break; 1013 case WLAN_ELEMID_EXTN_ELEM: 1014 status = util_scan_parse_extn_ie(scan_params, ie); 1015 if (QDF_IS_STATUS_ERROR(status)) 1016 goto err_status; 1017 break; 1018 case WLAN_ELEMID_REDUCED_NEIGHBOR_REPORT: 1019 if (ie->ie_len < WLAN_RNR_IE_MIN_LEN) 1020 goto err; 1021 scan_params->ie_list.rnrie = (uint8_t *)ie; 1022 status = util_scan_parse_rnr_ie(scan_params, ie); 1023 if (QDF_IS_STATUS_ERROR(status)) 1024 goto err_status; 1025 break; 1026 default: 1027 break; 1028 } 1029 1030 /* Consume info element */ 1031 ie_len -= ie->ie_len; 1032 /* Go to next IE */ 1033 ie = (struct ie_header *) 1034 (((uint8_t *) ie) + 1035 sizeof(struct ie_header) + 1036 ie->ie_len); 1037 } 1038 1039 return QDF_STATUS_SUCCESS; 1040 1041 err: 1042 status = QDF_STATUS_E_INVAL; 1043 err_status: 1044 scm_debug("failed to parse IE - id: %d, len: %d", 1045 ie->ie_id, ie->ie_len); 1046 1047 return status; 1048 } 1049 1050 /** 1051 * util_scan_update_esp_data: update ESP params from beacon/probe response 1052 * @esp_information: pointer to wlan_esp_information 1053 * @scan_entry: new received entry 1054 * 1055 * The Estimated Service Parameters element is 1056 * used by a AP to provide information to another STA which 1057 * can then use the information as input to an algorithm to 1058 * generate an estimate of throughput between the two STAs. 1059 * The ESP Information List field contains from 1 to 4 ESP 1060 * Information fields(each field 24 bits), each corresponding 1061 * to an access category for which estimated service parameters 1062 * information is provided. 1063 * 1064 * Return: None 1065 */ 1066 static void util_scan_update_esp_data(struct wlan_esp_ie *esp_information, 1067 struct scan_cache_entry *scan_entry) 1068 { 1069 1070 uint8_t *data; 1071 int i = 0; 1072 uint64_t total_elements; 1073 struct wlan_esp_info *esp_info; 1074 struct wlan_esp_ie *esp_ie; 1075 1076 esp_ie = (struct wlan_esp_ie *) 1077 util_scan_entry_esp_info(scan_entry); 1078 1079 total_elements = esp_ie->esp_len; 1080 data = (uint8_t *)esp_ie + 3; 1081 do_div(total_elements, ESP_INFORMATION_LIST_LENGTH); 1082 1083 if (total_elements > MAX_ESP_INFORMATION_FIELD) { 1084 scm_err("No of Air time fractions are greater than supported"); 1085 return; 1086 } 1087 1088 for (i = 0; i < total_elements; i++) { 1089 esp_info = (struct wlan_esp_info *)data; 1090 if (esp_info->access_category == ESP_AC_BK) { 1091 qdf_mem_copy(&esp_information->esp_info_AC_BK, 1092 data, 3); 1093 data = data + ESP_INFORMATION_LIST_LENGTH; 1094 continue; 1095 } 1096 if (esp_info->access_category == ESP_AC_BE) { 1097 qdf_mem_copy(&esp_information->esp_info_AC_BE, 1098 data, 3); 1099 data = data + ESP_INFORMATION_LIST_LENGTH; 1100 continue; 1101 } 1102 if (esp_info->access_category == ESP_AC_VI) { 1103 qdf_mem_copy(&esp_information->esp_info_AC_VI, 1104 data, 3); 1105 data = data + ESP_INFORMATION_LIST_LENGTH; 1106 continue; 1107 } 1108 if (esp_info->access_category == ESP_AC_VO) { 1109 qdf_mem_copy(&esp_information->esp_info_AC_VO, 1110 data, 3); 1111 data = data + ESP_INFORMATION_LIST_LENGTH; 1112 break; 1113 } 1114 } 1115 } 1116 1117 /** 1118 * util_scan_scm_update_bss_with_esp_dataa: calculate estimated air time 1119 * fraction 1120 * @scan_entry: new received entry 1121 * 1122 * This function process all Access category ESP params and provide 1123 * best effort air time fraction. 1124 * If best effort is not available, it will choose VI, VO and BK in sequence 1125 * 1126 */ 1127 static void util_scan_scm_update_bss_with_esp_data( 1128 struct scan_cache_entry *scan_entry) 1129 { 1130 uint8_t air_time_fraction = 0; 1131 struct wlan_esp_ie esp_information; 1132 1133 if (!scan_entry->ie_list.esp) 1134 return; 1135 1136 util_scan_update_esp_data(&esp_information, scan_entry); 1137 1138 /* 1139 * If the ESP metric is transmitting multiple airtime fractions, then 1140 * follow the sequence AC_BE, AC_VI, AC_VO, AC_BK and pick whichever is 1141 * the first one available 1142 */ 1143 if (esp_information.esp_info_AC_BE.access_category 1144 == ESP_AC_BE) 1145 air_time_fraction = 1146 esp_information.esp_info_AC_BE. 1147 estimated_air_fraction; 1148 else if (esp_information.esp_info_AC_VI.access_category 1149 == ESP_AC_VI) 1150 air_time_fraction = 1151 esp_information.esp_info_AC_VI. 1152 estimated_air_fraction; 1153 else if (esp_information.esp_info_AC_VO.access_category 1154 == ESP_AC_VO) 1155 air_time_fraction = 1156 esp_information.esp_info_AC_VO. 1157 estimated_air_fraction; 1158 else if (esp_information.esp_info_AC_BK.access_category 1159 == ESP_AC_BK) 1160 air_time_fraction = 1161 esp_information.esp_info_AC_BK. 1162 estimated_air_fraction; 1163 scan_entry->air_time_fraction = air_time_fraction; 1164 } 1165 1166 /** 1167 * util_scan_scm_calc_nss_supported_by_ap() - finds out nss from AP 1168 * @scan_entry: new received entry 1169 * 1170 * Return: number of nss advertised by AP 1171 */ 1172 static int util_scan_scm_calc_nss_supported_by_ap( 1173 struct scan_cache_entry *scan_params) 1174 { 1175 struct htcap_cmn_ie *htcap; 1176 struct wlan_ie_vhtcaps *vhtcaps; 1177 uint8_t rx_mcs_map; 1178 1179 htcap = (struct htcap_cmn_ie *) 1180 util_scan_entry_htcap(scan_params); 1181 vhtcaps = (struct wlan_ie_vhtcaps *) 1182 util_scan_entry_vhtcap(scan_params); 1183 if (vhtcaps) { 1184 rx_mcs_map = vhtcaps->rx_mcs_map; 1185 if ((rx_mcs_map & 0xC0) != 0xC0) 1186 return 4; 1187 1188 if ((rx_mcs_map & 0x30) != 0x30) 1189 return 3; 1190 1191 if ((rx_mcs_map & 0x0C) != 0x0C) 1192 return 2; 1193 } else if (htcap) { 1194 if (htcap->mcsset[3]) 1195 return 4; 1196 1197 if (htcap->mcsset[2]) 1198 return 3; 1199 1200 if (htcap->mcsset[1]) 1201 return 2; 1202 1203 } 1204 return 1; 1205 } 1206 1207 #ifdef WLAN_DFS_CHAN_HIDDEN_SSID 1208 QDF_STATUS 1209 util_scan_add_hidden_ssid(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t bcnbuf) 1210 { 1211 struct wlan_frame_hdr *hdr; 1212 struct wlan_bcn_frame *bcn; 1213 struct wlan_scan_obj *scan_obj; 1214 struct wlan_ssid *conf_ssid; 1215 struct ie_header *ie; 1216 uint32_t frame_len = qdf_nbuf_len(bcnbuf); 1217 uint16_t bcn_ie_offset, ssid_ie_start_offset, ssid_ie_end_offset; 1218 uint16_t tmplen, ie_length; 1219 uint8_t *pbeacon, *tmp; 1220 bool set_ssid_flag = false; 1221 struct ie_ssid *ssid; 1222 uint8_t pdev_id; 1223 1224 if (!pdev) { 1225 scm_warn("pdev: 0x%pK is NULL", pdev); 1226 return QDF_STATUS_E_NULL_VALUE; 1227 } 1228 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 1229 scan_obj = wlan_pdev_get_scan_obj(pdev); 1230 if (!scan_obj) { 1231 scm_warn("null scan_obj"); 1232 return QDF_STATUS_E_NULL_VALUE; 1233 } 1234 1235 conf_ssid = &scan_obj->pdev_info[pdev_id].conf_ssid; 1236 1237 hdr = (struct wlan_frame_hdr *)qdf_nbuf_data(bcnbuf); 1238 1239 /* received bssid does not match configured bssid */ 1240 if (qdf_mem_cmp(hdr->i_addr3, scan_obj->pdev_info[pdev_id].conf_bssid, 1241 QDF_MAC_ADDR_SIZE) || 1242 conf_ssid->length == 0) { 1243 return QDF_STATUS_SUCCESS; 1244 } 1245 1246 bcn = (struct wlan_bcn_frame *)(qdf_nbuf_data(bcnbuf) + sizeof(*hdr)); 1247 pbeacon = (uint8_t *)bcn; 1248 1249 ie = (struct ie_header *)(pbeacon + 1250 offsetof(struct wlan_bcn_frame, ie)); 1251 1252 bcn_ie_offset = offsetof(struct wlan_bcn_frame, ie); 1253 ie_length = (uint16_t)(frame_len - sizeof(*hdr) - 1254 bcn_ie_offset); 1255 1256 while (ie_length >= sizeof(struct ie_header)) { 1257 ie_length -= sizeof(struct ie_header); 1258 1259 bcn_ie_offset += sizeof(struct ie_header); 1260 1261 if (ie_length < ie->ie_len) { 1262 scm_debug("Incomplete corrupted IE:%x", ie->ie_id); 1263 return QDF_STATUS_E_INVAL; 1264 } 1265 if (ie->ie_id == WLAN_ELEMID_SSID) { 1266 if (ie->ie_len > (sizeof(struct ie_ssid) - 1267 sizeof(struct ie_header))) { 1268 return QDF_STATUS_E_INVAL; 1269 } 1270 ssid = (struct ie_ssid *)ie; 1271 if (util_scan_is_hidden_ssid(ssid)) { 1272 set_ssid_flag = true; 1273 ssid_ie_start_offset = bcn_ie_offset - 1274 sizeof(struct ie_header); 1275 ssid_ie_end_offset = bcn_ie_offset + 1276 ie->ie_len; 1277 } 1278 } 1279 if (ie->ie_len == 0) { 1280 ie += 1; /* next IE */ 1281 continue; 1282 } 1283 if (ie->ie_id == WLAN_ELEMID_VENDOR && 1284 is_wps_oui((uint8_t *)ie)) { 1285 set_ssid_flag = false; 1286 break; 1287 } 1288 /* Consume info element */ 1289 ie_length -= ie->ie_len; 1290 /* Go to next IE */ 1291 ie = (struct ie_header *)(((uint8_t *)ie) + 1292 sizeof(struct ie_header) + 1293 ie->ie_len); 1294 } 1295 1296 if (set_ssid_flag) { 1297 /* Hidden SSID if the Length is 0 */ 1298 if (!ssid->ssid_len) { 1299 /* increase the taillength by length of ssid */ 1300 if (qdf_nbuf_put_tail(bcnbuf, 1301 conf_ssid->length) == NULL) { 1302 scm_debug("No enough tailroom"); 1303 return QDF_STATUS_E_NOMEM; 1304 } 1305 /* length of the buffer to be copied */ 1306 tmplen = frame_len - 1307 sizeof(*hdr) - ssid_ie_end_offset; 1308 /* 1309 * tmp memory to copy the beacon info 1310 * after ssid ie. 1311 */ 1312 tmp = qdf_mem_malloc(tmplen * sizeof(u_int8_t)); 1313 if (!tmp) 1314 return QDF_STATUS_E_NOMEM; 1315 1316 /* Copy beacon data after ssid ie to tmp */ 1317 qdf_nbuf_copy_bits(bcnbuf, (sizeof(*hdr) + 1318 ssid_ie_end_offset), tmplen, tmp); 1319 /* Add ssid length */ 1320 *(pbeacon + (ssid_ie_start_offset + 1)) 1321 = conf_ssid->length; 1322 /* Insert the SSID string */ 1323 qdf_mem_copy((pbeacon + ssid_ie_end_offset), 1324 conf_ssid->ssid, conf_ssid->length); 1325 /* Copy rest of the beacon data */ 1326 qdf_mem_copy((pbeacon + ssid_ie_end_offset + 1327 conf_ssid->length), tmp, tmplen); 1328 qdf_mem_free(tmp); 1329 1330 /* Hidden ssid with all 0's */ 1331 } else if (ssid->ssid_len == conf_ssid->length) { 1332 /* Insert the SSID string */ 1333 qdf_mem_copy((pbeacon + ssid_ie_start_offset + 1334 sizeof(struct ie_header)), 1335 conf_ssid->ssid, conf_ssid->length); 1336 } else { 1337 scm_debug("mismatch in hidden ssid length"); 1338 return QDF_STATUS_E_INVAL; 1339 } 1340 } 1341 return QDF_STATUS_SUCCESS; 1342 } 1343 #endif /* WLAN_DFS_CHAN_HIDDEN_SSID */ 1344 1345 #ifdef WLAN_ADAPTIVE_11R 1346 /** 1347 * scm_fill_adaptive_11r_cap() - Check if the AP supports adaptive 11r 1348 * @scan_entry: Pointer to the scan entry 1349 * 1350 * Return: true if adaptive 11r is advertised else false 1351 */ 1352 static void scm_fill_adaptive_11r_cap(struct scan_cache_entry *scan_entry) 1353 { 1354 uint8_t *ie; 1355 uint8_t data; 1356 bool adaptive_11r; 1357 1358 ie = util_scan_entry_adaptive_11r(scan_entry); 1359 if (!ie) 1360 return; 1361 1362 data = *(ie + OUI_LENGTH); 1363 adaptive_11r = (data & 0x1) ? true : false; 1364 1365 scan_entry->adaptive_11r_ap = adaptive_11r; 1366 } 1367 #else 1368 static void scm_fill_adaptive_11r_cap(struct scan_cache_entry *scan_entry) 1369 { 1370 scan_entry->adaptive_11r_ap = false; 1371 } 1372 #endif 1373 1374 static QDF_STATUS 1375 util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev, 1376 uint8_t *frame, qdf_size_t frame_len, 1377 uint32_t frm_subtype, 1378 struct mgmt_rx_event_params *rx_param, 1379 struct scan_mbssid_info *mbssid_info, 1380 qdf_list_t *scan_list) 1381 { 1382 struct wlan_frame_hdr *hdr; 1383 struct wlan_bcn_frame *bcn; 1384 QDF_STATUS status = QDF_STATUS_SUCCESS; 1385 struct ie_ssid *ssid; 1386 struct scan_cache_entry *scan_entry; 1387 struct qbss_load_ie *qbss_load; 1388 struct scan_cache_node *scan_node; 1389 uint8_t i, chan_idx = 0; 1390 1391 scan_entry = qdf_mem_malloc_atomic(sizeof(*scan_entry)); 1392 if (!scan_entry) { 1393 scm_err("failed to allocate memory for scan_entry"); 1394 return QDF_STATUS_E_NOMEM; 1395 } 1396 scan_entry->raw_frame.ptr = 1397 qdf_mem_malloc_atomic(frame_len); 1398 if (!scan_entry->raw_frame.ptr) { 1399 scm_err("failed to allocate memory for frame"); 1400 qdf_mem_free(scan_entry); 1401 return QDF_STATUS_E_NOMEM; 1402 } 1403 1404 bcn = (struct wlan_bcn_frame *) 1405 (frame + sizeof(*hdr)); 1406 hdr = (struct wlan_frame_hdr *)frame; 1407 1408 /* update timestamp in nanoseconds needed by kernel layers */ 1409 scan_entry->boottime_ns = qdf_get_bootbased_boottime_ns(); 1410 1411 scan_entry->frm_subtype = frm_subtype; 1412 qdf_mem_copy(scan_entry->bssid.bytes, 1413 hdr->i_addr3, QDF_MAC_ADDR_SIZE); 1414 /* Scr addr */ 1415 qdf_mem_copy(scan_entry->mac_addr.bytes, 1416 hdr->i_addr2, QDF_MAC_ADDR_SIZE); 1417 scan_entry->seq_num = 1418 (le16toh(*(uint16_t *)hdr->i_seq) >> WLAN_SEQ_SEQ_SHIFT); 1419 1420 scan_entry->snr = rx_param->snr; 1421 scan_entry->avg_snr = WLAN_SNR_IN(scan_entry->snr); 1422 scan_entry->rssi_raw = rx_param->rssi; 1423 scan_entry->avg_rssi = WLAN_RSSI_IN(scan_entry->rssi_raw); 1424 scan_entry->tsf_delta = rx_param->tsf_delta; 1425 scan_entry->pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 1426 1427 /* Copy per chain rssi to scan entry */ 1428 qdf_mem_copy(scan_entry->per_chain_rssi, rx_param->rssi_ctl, 1429 WLAN_MGMT_TXRX_HOST_MAX_ANTENNA); 1430 1431 if (!wlan_psoc_nif_fw_ext_cap_get(wlan_pdev_get_psoc(pdev), 1432 WLAN_SOC_CEXT_HW_DB2DBM)) { 1433 for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++) { 1434 if (scan_entry->per_chain_rssi[i] != 1435 WLAN_INVALID_PER_CHAIN_SNR) 1436 scan_entry->per_chain_rssi[i] += 1437 WLAN_NOISE_FLOOR_DBM_DEFAULT; 1438 else 1439 scan_entry->per_chain_rssi[i] = 1440 WLAN_INVALID_PER_CHAIN_RSSI; 1441 } 1442 } 1443 1444 /* store jiffies */ 1445 scan_entry->rrm_parent_tsf = (uint32_t)qdf_system_ticks(); 1446 1447 scan_entry->bcn_int = le16toh(bcn->beacon_interval); 1448 1449 /* 1450 * In case if the beacon dosnt have 1451 * valid beacon interval falback to def 1452 */ 1453 if (!scan_entry->bcn_int) 1454 scan_entry->bcn_int = 100; 1455 scan_entry->cap_info.value = le16toh(bcn->capability.value); 1456 qdf_mem_copy(scan_entry->tsf_info.data, 1457 bcn->timestamp, 8); 1458 scan_entry->erp = ERP_NON_ERP_PRESENT; 1459 1460 scan_entry->scan_entry_time = 1461 qdf_mc_timer_get_system_time(); 1462 1463 scan_entry->raw_frame.len = frame_len; 1464 qdf_mem_copy(scan_entry->raw_frame.ptr, 1465 frame, frame_len); 1466 status = util_scan_populate_bcn_ie_list(scan_entry, &chan_idx); 1467 if (QDF_IS_STATUS_ERROR(status)) { 1468 scm_debug("failed to parse beacon IE"); 1469 qdf_mem_free(scan_entry->raw_frame.ptr); 1470 qdf_mem_free(scan_entry); 1471 return QDF_STATUS_E_FAILURE; 1472 } 1473 1474 ssid = (struct ie_ssid *) 1475 scan_entry->ie_list.ssid; 1476 1477 if (ssid && (ssid->ssid_len > WLAN_SSID_MAX_LEN)) { 1478 qdf_mem_free(scan_entry->raw_frame.ptr); 1479 qdf_mem_free(scan_entry); 1480 return QDF_STATUS_E_FAILURE; 1481 } 1482 1483 if (scan_entry->ie_list.p2p) 1484 scan_entry->is_p2p = true; 1485 1486 if (!chan_idx && util_scan_entry_hecap(scan_entry)) 1487 util_scan_get_chan_from_he_6g_params(scan_entry, &chan_idx); 1488 1489 if (chan_idx) { 1490 uint8_t band_mask = BIT(wlan_reg_freq_to_band( 1491 rx_param->chan_freq)); 1492 1493 scan_entry->channel.chan_freq = 1494 wlan_reg_chan_band_to_freq( 1495 pdev, chan_idx, 1496 band_mask); 1497 } 1498 /* If no channel info is present in beacon use meta channel */ 1499 if (!scan_entry->channel.chan_freq) { 1500 scan_entry->channel.chan_freq = rx_param->chan_freq; 1501 } else if (rx_param->chan_freq != 1502 scan_entry->channel.chan_freq) { 1503 if (!wlan_reg_is_49ghz_freq(scan_entry->channel.chan_freq)) 1504 scan_entry->channel_mismatch = true; 1505 } 1506 1507 if (util_scan_is_hidden_ssid(ssid)) { 1508 scan_entry->ie_list.ssid = NULL; 1509 scan_entry->is_hidden_ssid = true; 1510 } else { 1511 qdf_mem_copy(scan_entry->ssid.ssid, 1512 ssid->ssid, ssid->ssid_len); 1513 scan_entry->ssid.length = ssid->ssid_len; 1514 scan_entry->hidden_ssid_timestamp = 1515 scan_entry->scan_entry_time; 1516 } 1517 qdf_mem_copy(&scan_entry->mbssid_info, mbssid_info, 1518 sizeof(scan_entry->mbssid_info)); 1519 1520 scan_entry->phy_mode = util_scan_get_phymode(pdev, scan_entry); 1521 1522 scan_entry->nss = util_scan_scm_calc_nss_supported_by_ap(scan_entry); 1523 scm_fill_adaptive_11r_cap(scan_entry); 1524 1525 util_scan_scm_update_bss_with_esp_data(scan_entry); 1526 qbss_load = (struct qbss_load_ie *) 1527 util_scan_entry_qbssload(scan_entry); 1528 if (qbss_load) 1529 scan_entry->qbss_chan_load = qbss_load->qbss_chan_load; 1530 1531 scan_node = qdf_mem_malloc_atomic(sizeof(*scan_node)); 1532 if (!scan_node) { 1533 qdf_mem_free(scan_entry->raw_frame.ptr); 1534 qdf_mem_free(scan_entry); 1535 return QDF_STATUS_E_FAILURE; 1536 } 1537 1538 scan_node->entry = scan_entry; 1539 qdf_list_insert_front(scan_list, &scan_node->node); 1540 1541 return status; 1542 } 1543 1544 /** 1545 * util_scan_find_ie() - find information element 1546 * @eid: element id 1547 * @ies: pointer consisting of IEs 1548 * @len: IE length 1549 * 1550 * Return: NULL if the element ID is not found or 1551 * a pointer to the first byte of the requested 1552 * element 1553 */ 1554 static uint8_t *util_scan_find_ie(uint8_t eid, uint8_t *ies, 1555 int32_t len) 1556 { 1557 while (len >= 2 && len >= ies[1] + 2) { 1558 if (ies[0] == eid) 1559 return ies; 1560 len -= ies[1] + 2; 1561 ies += ies[1] + 2; 1562 } 1563 1564 return NULL; 1565 } 1566 1567 #ifdef WLAN_FEATURE_MBSSID 1568 static void util_gen_new_bssid(uint8_t *bssid, uint8_t max_bssid, 1569 uint8_t mbssid_index, 1570 uint8_t *new_bssid_addr) 1571 { 1572 uint8_t lsb_n; 1573 int i; 1574 1575 for (i = 0; i < QDF_MAC_ADDR_SIZE; i++) 1576 new_bssid_addr[i] = bssid[i]; 1577 1578 lsb_n = new_bssid_addr[5] & ((1 << max_bssid) - 1); 1579 1580 new_bssid_addr[5] &= ~((1 << max_bssid) - 1); 1581 new_bssid_addr[5] |= (lsb_n + mbssid_index) % (1 << max_bssid); 1582 } 1583 1584 static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, 1585 uint8_t *subelement, 1586 size_t subie_len, uint8_t *new_ie) 1587 { 1588 uint8_t *pos, *tmp; 1589 const uint8_t *tmp_old, *tmp_new; 1590 uint8_t *sub_copy; 1591 1592 /* copy subelement as we need to change its content to 1593 * mark an ie after it is processed. 1594 */ 1595 sub_copy = qdf_mem_malloc(subie_len); 1596 if (!sub_copy) 1597 return 0; 1598 qdf_mem_copy(sub_copy, subelement, subie_len); 1599 1600 pos = &new_ie[0]; 1601 1602 /* new ssid */ 1603 tmp_new = util_scan_find_ie(WLAN_ELEMID_SSID, sub_copy, subie_len); 1604 if (tmp_new) { 1605 qdf_mem_copy(pos, tmp_new, tmp_new[1] + 2); 1606 pos += (tmp_new[1] + 2); 1607 } 1608 1609 /* go through IEs in ie (skip SSID) and subelement, 1610 * merge them into new_ie 1611 */ 1612 tmp_old = util_scan_find_ie(WLAN_ELEMID_SSID, ie, ielen); 1613 tmp_old = (tmp_old) ? tmp_old + tmp_old[1] + 2 : ie; 1614 1615 while (tmp_old + tmp_old[1] + 2 - ie <= ielen) { 1616 if (tmp_old[0] == 0) { 1617 tmp_old++; 1618 continue; 1619 } 1620 1621 tmp = (uint8_t *)util_scan_find_ie(tmp_old[0], sub_copy, 1622 subie_len); 1623 if (!tmp) { 1624 /* ie in old ie but not in subelement */ 1625 if (tmp_old[0] != WLAN_ELEMID_MULTIPLE_BSSID) { 1626 qdf_mem_copy(pos, tmp_old, tmp_old[1] + 2); 1627 pos += tmp_old[1] + 2; 1628 } 1629 } else { 1630 /* ie in transmitting ie also in subelement, 1631 * copy from subelement and flag the ie in subelement 1632 * as copied (by setting eid field to 0xff). For 1633 * vendor ie, compare OUI + type + subType to 1634 * determine if they are the same ie. 1635 */ 1636 if (tmp_old[0] == WLAN_ELEMID_VENDOR) { 1637 if (!qdf_mem_cmp(tmp_old + 2, tmp + 2, 5)) { 1638 /* same vendor ie, copy from 1639 * subelement 1640 */ 1641 qdf_mem_copy(pos, tmp, tmp[1] + 2); 1642 pos += tmp[1] + 2; 1643 tmp[0] = 0xff; 1644 } else { 1645 qdf_mem_copy(pos, tmp_old, 1646 tmp_old[1] + 2); 1647 pos += tmp_old[1] + 2; 1648 } 1649 } else { 1650 /* copy ie from subelement into new ie */ 1651 qdf_mem_copy(pos, tmp, tmp[1] + 2); 1652 pos += tmp[1] + 2; 1653 tmp[0] = 0xff; 1654 } 1655 } 1656 1657 if (tmp_old + tmp_old[1] + 2 - ie == ielen) 1658 break; 1659 1660 tmp_old += tmp_old[1] + 2; 1661 } 1662 1663 /* go through subelement again to check if there is any ie not 1664 * copied to new ie, skip ssid, capability, bssid-index ie 1665 */ 1666 tmp_new = sub_copy; 1667 while (tmp_new + tmp_new[1] + 2 - sub_copy <= subie_len) { 1668 if (!(tmp_new[0] == WLAN_ELEMID_NONTX_BSSID_CAP || 1669 tmp_new[0] == WLAN_ELEMID_SSID || 1670 tmp_new[0] == WLAN_ELEMID_MULTI_BSSID_IDX || 1671 tmp_new[0] == 0xff)) { 1672 qdf_mem_copy(pos, tmp_new, tmp_new[1] + 2); 1673 pos += tmp_new[1] + 2; 1674 } 1675 if (tmp_new + tmp_new[1] + 2 - sub_copy == subie_len) 1676 break; 1677 tmp_new += tmp_new[1] + 2; 1678 } 1679 1680 qdf_mem_free(sub_copy); 1681 return pos - new_ie; 1682 } 1683 1684 static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, 1685 uint8_t *frame, qdf_size_t frame_len, 1686 uint32_t frm_subtype, 1687 struct mgmt_rx_event_params *rx_param, 1688 qdf_list_t *scan_list) 1689 { 1690 struct wlan_bcn_frame *bcn; 1691 struct wlan_frame_hdr *hdr; 1692 struct scan_mbssid_info mbssid_info; 1693 QDF_STATUS status; 1694 uint8_t *pos, *subelement, *mbssid_end_pos; 1695 uint8_t *tmp, *mbssid_index_ie; 1696 uint32_t subie_len, new_ie_len; 1697 uint8_t new_bssid[QDF_MAC_ADDR_SIZE], bssid[QDF_MAC_ADDR_SIZE]; 1698 uint8_t *new_ie; 1699 uint8_t *ie, *new_frame = NULL; 1700 uint64_t ielen, new_frame_len; 1701 1702 hdr = (struct wlan_frame_hdr *)frame; 1703 bcn = (struct wlan_bcn_frame *)(frame + sizeof(struct wlan_frame_hdr)); 1704 ie = (uint8_t *)&bcn->ie; 1705 ielen = (uint16_t)(frame_len - 1706 sizeof(struct wlan_frame_hdr) - 1707 offsetof(struct wlan_bcn_frame, ie)); 1708 qdf_mem_copy(bssid, hdr->i_addr3, QDF_MAC_ADDR_SIZE); 1709 1710 if (!util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, ie, ielen)) 1711 return QDF_STATUS_E_FAILURE; 1712 1713 pos = ie; 1714 1715 new_ie = qdf_mem_malloc(MAX_IE_LEN); 1716 if (!new_ie) 1717 return QDF_STATUS_E_NOMEM; 1718 1719 while (pos < ie + ielen + 2) { 1720 tmp = util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, pos, 1721 ielen - (pos - ie)); 1722 if (!tmp) 1723 break; 1724 1725 mbssid_info.profile_count = 1 << tmp[2]; 1726 mbssid_end_pos = tmp + tmp[1] + 2; 1727 /* Skip Element ID, Len, MaxBSSID Indicator */ 1728 if (tmp[1] < 4) 1729 break; 1730 for (subelement = tmp + 3; subelement < mbssid_end_pos - 1; 1731 subelement += 2 + subelement[1]) { 1732 subie_len = subelement[1]; 1733 if (mbssid_end_pos - subelement < 2 + subie_len) 1734 break; 1735 if (subelement[0] != 0 || subelement[1] < 4) { 1736 /* not a valid BSS profile */ 1737 continue; 1738 } 1739 1740 if (subelement[2] != WLAN_ELEMID_NONTX_BSSID_CAP || 1741 subelement[3] != 2) { 1742 /* The first element within the Nontransmitted 1743 * BSSID Profile is not the Nontransmitted 1744 * BSSID Capability element. 1745 */ 1746 continue; 1747 } 1748 1749 /* found a Nontransmitted BSSID Profile */ 1750 mbssid_index_ie = 1751 util_scan_find_ie(WLAN_ELEMID_MULTI_BSSID_IDX, 1752 subelement + 2, subie_len); 1753 if (!mbssid_index_ie || mbssid_index_ie[1] < 1 || 1754 mbssid_index_ie[2] == 0) { 1755 /* No valid Multiple BSSID-Index element */ 1756 continue; 1757 } 1758 qdf_mem_copy(&mbssid_info.trans_bssid, bssid, 1759 QDF_MAC_ADDR_SIZE); 1760 mbssid_info.profile_num = mbssid_index_ie[2]; 1761 util_gen_new_bssid(bssid, tmp[2], mbssid_index_ie[2], 1762 new_bssid); 1763 new_ie_len = util_gen_new_ie(ie, ielen, subelement + 2, 1764 subie_len, new_ie); 1765 if (!new_ie_len) 1766 continue; 1767 1768 new_frame_len = frame_len - ielen + new_ie_len; 1769 new_frame = qdf_mem_malloc(new_frame_len); 1770 if (!new_frame) { 1771 qdf_mem_free(new_ie); 1772 return QDF_STATUS_E_NOMEM; 1773 } 1774 1775 /* 1776 * Copy the header(24byte), timestamp(8 byte), 1777 * beaconinterval(2byte) and capability(2byte) 1778 */ 1779 qdf_mem_copy(new_frame, frame, 36); 1780 /* Copy the new ie generated from MBSSID profile*/ 1781 hdr = (struct wlan_frame_hdr *)new_frame; 1782 qdf_mem_copy(hdr->i_addr2, new_bssid, 1783 QDF_MAC_ADDR_SIZE); 1784 qdf_mem_copy(hdr->i_addr3, new_bssid, 1785 QDF_MAC_ADDR_SIZE); 1786 /* Copy the new ie generated from MBSSID profile*/ 1787 qdf_mem_copy(new_frame + 1788 offsetof(struct wlan_bcn_frame, ie) + 1789 sizeof(struct wlan_frame_hdr), 1790 new_ie, new_ie_len); 1791 status = util_scan_gen_scan_entry(pdev, new_frame, 1792 new_frame_len, 1793 frm_subtype, 1794 rx_param, 1795 &mbssid_info, 1796 scan_list); 1797 if (QDF_IS_STATUS_ERROR(status)) { 1798 qdf_mem_free(new_frame); 1799 scm_err("failed to generate a scan entry"); 1800 break; 1801 } 1802 /* scan entry makes its own copy so free the frame*/ 1803 qdf_mem_free(new_frame); 1804 } 1805 1806 pos = mbssid_end_pos; 1807 } 1808 qdf_mem_free(new_ie); 1809 1810 return QDF_STATUS_SUCCESS; 1811 } 1812 #else 1813 static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, 1814 uint8_t *frame, qdf_size_t frame_len, 1815 uint32_t frm_subtype, 1816 struct mgmt_rx_event_params *rx_param, 1817 qdf_list_t *scan_list) 1818 { 1819 return QDF_STATUS_SUCCESS; 1820 } 1821 #endif 1822 1823 static QDF_STATUS 1824 util_scan_parse_beacon_frame(struct wlan_objmgr_pdev *pdev, 1825 uint8_t *frame, 1826 qdf_size_t frame_len, 1827 uint32_t frm_subtype, 1828 struct mgmt_rx_event_params *rx_param, 1829 qdf_list_t *scan_list) 1830 { 1831 struct wlan_bcn_frame *bcn; 1832 struct wlan_frame_hdr *hdr; 1833 uint8_t *mbssid_ie = NULL; 1834 uint32_t ie_len = 0; 1835 QDF_STATUS status; 1836 struct scan_mbssid_info mbssid_info = { 0 }; 1837 1838 hdr = (struct wlan_frame_hdr *)frame; 1839 bcn = (struct wlan_bcn_frame *) 1840 (frame + sizeof(struct wlan_frame_hdr)); 1841 ie_len = (uint16_t)(frame_len - 1842 sizeof(struct wlan_frame_hdr) - 1843 offsetof(struct wlan_bcn_frame, ie)); 1844 1845 mbssid_ie = util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, 1846 (uint8_t *)&bcn->ie, ie_len); 1847 if (mbssid_ie) { 1848 qdf_mem_copy(&mbssid_info.trans_bssid, 1849 hdr->i_addr3, QDF_MAC_ADDR_SIZE); 1850 mbssid_info.profile_count = 1 << mbssid_ie[2]; 1851 } 1852 1853 status = util_scan_gen_scan_entry(pdev, frame, frame_len, 1854 frm_subtype, rx_param, 1855 &mbssid_info, 1856 scan_list); 1857 1858 /* 1859 * IF MBSSID IE is present in the beacon then 1860 * scan component will create a new entry for 1861 * each BSSID found in the MBSSID 1862 */ 1863 if (mbssid_ie) 1864 status = util_scan_parse_mbssid(pdev, frame, frame_len, 1865 frm_subtype, rx_param, 1866 scan_list); 1867 1868 if (QDF_IS_STATUS_ERROR(status)) 1869 scm_debug_rl("Failed to create a scan entry"); 1870 1871 return status; 1872 } 1873 1874 qdf_list_t * 1875 util_scan_unpack_beacon_frame(struct wlan_objmgr_pdev *pdev, uint8_t *frame, 1876 qdf_size_t frame_len, uint32_t frm_subtype, 1877 struct mgmt_rx_event_params *rx_param) 1878 { 1879 qdf_list_t *scan_list; 1880 QDF_STATUS status; 1881 1882 scan_list = qdf_mem_malloc_atomic(sizeof(*scan_list)); 1883 if (!scan_list) { 1884 scm_err("failed to allocate scan_list"); 1885 return NULL; 1886 } 1887 qdf_list_create(scan_list, MAX_SCAN_CACHE_SIZE); 1888 1889 status = util_scan_parse_beacon_frame(pdev, frame, frame_len, 1890 frm_subtype, rx_param, 1891 scan_list); 1892 if (QDF_IS_STATUS_ERROR(status)) { 1893 ucfg_scan_purge_results(scan_list); 1894 return NULL; 1895 } 1896 1897 return scan_list; 1898 } 1899 1900 QDF_STATUS 1901 util_scan_entry_update_mlme_info(struct wlan_objmgr_pdev *pdev, 1902 struct scan_cache_entry *scan_entry) 1903 { 1904 1905 if (!pdev || !scan_entry) { 1906 scm_err("pdev 0x%pK, scan_entry: 0x%pK", pdev, scan_entry); 1907 return QDF_STATUS_E_INVAL; 1908 } 1909 1910 return scm_update_scan_mlme_info(pdev, scan_entry); 1911 } 1912 1913 bool util_is_scan_completed(struct scan_event *event, bool *success) 1914 { 1915 if ((event->type == SCAN_EVENT_TYPE_COMPLETED) || 1916 (event->type == SCAN_EVENT_TYPE_DEQUEUED) || 1917 (event->type == SCAN_EVENT_TYPE_START_FAILED)) { 1918 if ((event->type == SCAN_EVENT_TYPE_COMPLETED) && 1919 (event->reason == SCAN_REASON_COMPLETED)) 1920 *success = true; 1921 else 1922 *success = false; 1923 1924 return true; 1925 } 1926 1927 *success = false; 1928 return false; 1929 } 1930 1931