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