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