1 /* 2 * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: lim_send_frames_host_roam.c 22 * 23 * Send management frames for host based roaming 24 */ 25 #include "sir_api.h" 26 #include "ani_global.h" 27 #include "sir_mac_prot_def.h" 28 #include "utils_api.h" 29 #include "lim_types.h" 30 #include "lim_utils.h" 31 #include "lim_security_utils.h" 32 #include "lim_prop_exts_utils.h" 33 #include "dot11f.h" 34 #include "sch_api.h" 35 #include "lim_send_messages.h" 36 #include "lim_assoc_utils.h" 37 #include "lim_ft.h" 38 #include "wni_cfg.h" 39 40 #include "lim_ft_defs.h" 41 #include "lim_session.h" 42 #include "qdf_types.h" 43 #include "qdf_trace.h" 44 #include "cds_utils.h" 45 #include "sme_trace.h" 46 #include "rrm_api.h" 47 48 #include "wma_types.h" 49 #include "wlan_utility.h" 50 51 /** 52 * lim_send_reassoc_req_with_ft_ies_mgmt_frame() - Send Reassoc Req with FTIEs. 53 * 54 * @mac_ctx: Handle to mac context 55 * @mlm_reassoc_req: Original reassoc request 56 * @pe_session: PE session information 57 * 58 * It builds a reassoc request with FT IEs and sends it to AP through WMA. 59 * Then it creates assoc request and stores it for sending after join 60 * confirmation. 61 * 62 * Return: None 63 */ lim_send_reassoc_req_with_ft_ies_mgmt_frame(struct mac_context * mac_ctx,tLimMlmReassocReq * mlm_reassoc_req,struct pe_session * pe_session)64 void lim_send_reassoc_req_with_ft_ies_mgmt_frame(struct mac_context *mac_ctx, 65 tLimMlmReassocReq *mlm_reassoc_req, 66 struct pe_session *pe_session) 67 { 68 tDot11fReAssocRequest *frm; 69 uint16_t caps; 70 uint8_t *frame; 71 uint32_t bytes, payload, status; 72 uint8_t qos_enabled, wme_enabled, wsm_enabled; 73 void *packet; 74 QDF_STATUS qdf_status; 75 uint8_t power_caps_populated = false; 76 uint16_t ft_ies_length = 0; 77 uint8_t *body; 78 uint16_t add_ie_len; 79 uint8_t *add_ie; 80 const uint8_t *wps_ie = NULL; 81 uint8_t tx_flag = 0; 82 uint8_t vdev_id = 0; 83 bool vht_enabled = false; 84 tpSirMacMgmtHdr mac_hdr; 85 struct mlme_legacy_priv *mlme_priv; 86 int ret; 87 tDot11fIEExtCap extr_ext_cap; 88 QDF_STATUS sir_status; 89 bool extr_ext_flag = true; 90 uint32_t ie_offset = 0; 91 tDot11fIEExtCap bcn_ext_cap; 92 uint8_t *bcn_ie = NULL; 93 uint32_t bcn_ie_len = 0; 94 uint8_t *p_ext_cap = NULL; 95 96 if (!pe_session) 97 return; 98 99 mlme_priv = wlan_vdev_mlme_get_ext_hdl(pe_session->vdev); 100 if (!mlme_priv) 101 return; 102 103 vdev_id = pe_session->vdev_id; 104 105 /* check this early to avoid unnecessary operation */ 106 if (!pe_session->pLimReAssocReq) 107 return; 108 109 frm = qdf_mem_malloc(sizeof(*frm)); 110 if (!frm) 111 goto err; 112 113 add_ie_len = pe_session->pLimReAssocReq->addIEAssoc.length; 114 add_ie = pe_session->pLimReAssocReq->addIEAssoc.addIEdata; 115 pe_debug("called in state: %d", pe_session->limMlmState); 116 117 qdf_mem_zero((uint8_t *) frm, sizeof(*frm)); 118 119 if (add_ie_len && pe_session->is_ext_caps_present) { 120 qdf_mem_zero((uint8_t *)&extr_ext_cap, 121 sizeof(tDot11fIEExtCap)); 122 sir_status = lim_strip_extcap_update_struct( 123 mac_ctx, add_ie, &add_ie_len, &extr_ext_cap); 124 if (QDF_STATUS_SUCCESS != sir_status) { 125 extr_ext_flag = false; 126 pe_debug("Unable to Stripoff ExtCap IE from Assoc Req"); 127 } else { 128 struct s_ext_cap *p_ext_cap = (struct s_ext_cap *) 129 extr_ext_cap.bytes; 130 131 if (p_ext_cap->interworking_service) 132 p_ext_cap->qos_map = 1; 133 extr_ext_cap.num_bytes = 134 lim_compute_ext_cap_ie_length(&extr_ext_cap); 135 extr_ext_flag = (extr_ext_cap.num_bytes > 0); 136 } 137 } else { 138 pe_debug("No addn IE or peer doesn't support addnIE for Assoc Req"); 139 extr_ext_flag = false; 140 } 141 caps = mlm_reassoc_req->capabilityInfo; 142 #if defined(FEATURE_WLAN_WAPI) 143 /* 144 * According to WAPI standard: 145 * 7.3.1.4 Capability Information field 146 * In WAPI, non-AP STAs within an ESS set the Privacy subfield 147 * to 0 in transmitted Association or Reassociation management 148 * frames. APs ignore the Privacy subfield within received 149 * Association and Reassociation management frames. 150 */ 151 if (pe_session->encryptType == eSIR_ED_WPI) 152 ((tSirMacCapabilityInfo *) &caps)->privacy = 0; 153 #endif 154 swap_bit_field16(caps, (uint16_t *) &frm->Capabilities); 155 156 frm->ListenInterval.interval = mlm_reassoc_req->listenInterval; 157 158 /* 159 * Get the old bssid of the older AP. 160 * The previous ap bssid is stored in the FT Session 161 * while creating the PE FT Session for reassociation. 162 */ 163 qdf_mem_copy((uint8_t *)frm->CurrentAPAddress.mac, 164 pe_session->prev_ap_bssid, sizeof(tSirMacAddr)); 165 166 populate_dot11f_ssid2(pe_session, &frm->SSID); 167 populate_dot11f_supp_rates(mac_ctx, POPULATE_DOT11F_RATES_OPERATIONAL, 168 &frm->SuppRates, pe_session); 169 170 qos_enabled = (pe_session->limQosEnabled) && 171 SIR_MAC_GET_QOS(pe_session->limReassocBssCaps); 172 173 wme_enabled = (pe_session->limWmeEnabled) && 174 LIM_BSS_CAPS_GET(WME, pe_session->limReassocBssQosCaps); 175 176 wsm_enabled = (pe_session->limWsmEnabled) && wme_enabled && 177 LIM_BSS_CAPS_GET(WSM, pe_session->limReassocBssQosCaps); 178 179 if (pe_session->lim11hEnable && 180 pe_session->spectrumMgtEnabled) { 181 power_caps_populated = true; 182 183 populate_dot11f_power_caps(mac_ctx, &frm->PowerCaps, 184 LIM_REASSOC, pe_session); 185 populate_dot11f_supp_channels(mac_ctx, &frm->SuppChannels, 186 LIM_REASSOC, pe_session); 187 } 188 if (mac_ctx->rrm.rrmPEContext.rrmEnable && 189 SIR_MAC_GET_RRM(pe_session->limCurrentBssCaps)) { 190 if (power_caps_populated == false) { 191 power_caps_populated = true; 192 populate_dot11f_power_caps(mac_ctx, &frm->PowerCaps, 193 LIM_REASSOC, pe_session); 194 } 195 } 196 197 if (qos_enabled) 198 populate_dot11f_qos_caps_station(mac_ctx, pe_session, 199 &frm->QOSCapsStation); 200 201 populate_dot11f_ext_supp_rates(mac_ctx, 202 POPULATE_DOT11F_RATES_OPERATIONAL, &frm->ExtSuppRates, 203 pe_session); 204 205 if (mac_ctx->rrm.rrmPEContext.rrmEnable && 206 SIR_MAC_GET_RRM(pe_session->limCurrentBssCaps)) 207 populate_dot11f_rrm_ie(mac_ctx, &frm->RRMEnabledCap, pe_session); 208 209 /* 210 * Ideally this should be enabled for 11r also. But 11r does 211 * not follow the usual norm of using the Opaque object 212 * for rsnie and fties. Instead we just add the rsnie and fties 213 * at the end of the pack routine for 11r. 214 * This should ideally! be fixed. 215 */ 216 /* 217 * The join request *should* contain zero or one of the WPA and RSN 218 * IEs. The payload send along with the request is a 219 * 'struct join_req'; the IE portion is held inside a 'tSirRSNie': 220 * 221 * typedef struct sSirRSNie 222 * { 223 * uint16_t length; 224 * uint8_t rsnIEdata[WLAN_MAX_IE_LEN+2]; 225 * } tSirRSNie, *tpSirRSNie; 226 * 227 * So, we should be able to make the following two calls harmlessly, 228 * since they do nothing if they don't find the given IE in the 229 * bytestream with which they're provided. 230 * 231 * The net effect of this will be to faithfully transmit whatever 232 * security IE is in the join request. 233 234 * However, if we're associating for the purpose of WPS 235 * enrollment, and we've been configured to indicate that by 236 * eliding the WPA or RSN IE, we just skip this: 237 */ 238 if (!pe_session->is11Rconnection) { 239 if (add_ie_len && add_ie) 240 wps_ie = limGetWscIEPtr(mac_ctx, add_ie, add_ie_len); 241 if (!wps_ie) { 242 populate_dot11f_rsn_opaque(mac_ctx, 243 &(pe_session->pLimReAssocReq->rsnIE), 244 &frm->RSNOpaque); 245 populate_dot11f_wpa_opaque(mac_ctx, 246 &(pe_session->pLimReAssocReq->rsnIE), 247 &frm->WPAOpaque); 248 } 249 #ifdef FEATURE_WLAN_ESE 250 if (mlme_priv->connect_info.cckm_ie_len) { 251 populate_dot11f_ese_cckm_opaque(mac_ctx, 252 &mlme_priv->connect_info, 253 &frm->ESECckmOpaque); 254 } 255 #endif 256 } 257 #ifdef FEATURE_WLAN_ESE 258 /* 259 * ESE Version IE will be included in re-association request 260 * when ESE is enabled on DUT through ini and it is also 261 * advertised by the peer AP to which we are trying to 262 * associate to. 263 */ 264 if (pe_session->is_ese_version_ie_present && 265 mac_ctx->mlme_cfg->lfr.ese_enabled) 266 populate_dot11f_ese_version(&frm->ESEVersion); 267 /* For ESE Associations fill the ESE IEs */ 268 if (wlan_cm_get_ese_assoc(mac_ctx->pdev, vdev_id)) { 269 #ifndef FEATURE_DISABLE_RM 270 populate_dot11f_ese_rad_mgmt_cap(&frm->ESERadMgmtCap); 271 #endif 272 } 273 #endif /* FEATURE_WLAN_ESE */ 274 275 /* include WME EDCA IE as well */ 276 if (wme_enabled) { 277 populate_dot11f_wmm_info_station_per_session(mac_ctx, 278 pe_session, &frm->WMMInfoStation); 279 if (wsm_enabled) 280 populate_dot11f_wmm_caps(&frm->WMMCaps); 281 #ifdef FEATURE_WLAN_ESE 282 if (wlan_cm_get_ese_assoc(mac_ctx->pdev, vdev_id)) { 283 uint32_t phymode; 284 uint8_t rate; 285 286 populate_dot11f_re_assoc_tspec(mac_ctx, frm, 287 pe_session); 288 289 /* 290 * Populate the TSRS IE if TSPEC is included in 291 * the reassoc request 292 */ 293 lim_get_phy_mode(mac_ctx, &phymode, pe_session); 294 if (phymode == WNI_CFG_PHY_MODE_11G || 295 phymode == WNI_CFG_PHY_MODE_11A) 296 rate = TSRS_11AG_RATE_6MBPS; 297 else 298 rate = TSRS_11B_RATE_5_5MBPS; 299 300 if (mlme_priv->connect_info.ese_tspec_info.numTspecs) 301 { 302 struct ese_tsrs_ie tsrs_ie; 303 304 tsrs_ie.tsid = 0; 305 tsrs_ie.rates[0] = rate; 306 populate_dot11_tsrsie(mac_ctx, &tsrs_ie, 307 &frm->ESETrafStrmRateSet, 308 sizeof(uint8_t)); 309 } 310 } 311 #endif 312 } 313 314 if (pe_session->htCapability && 315 mac_ctx->lim.htCapabilityPresentInBeacon) { 316 populate_dot11f_ht_caps(mac_ctx, pe_session, &frm->HTCaps); 317 } 318 if (pe_session->pLimReAssocReq->bssDescription.mdiePresent && 319 (mlme_priv->connect_info.ft_info.add_mdie) 320 #if defined FEATURE_WLAN_ESE 321 && !wlan_cm_get_ese_assoc(mac_ctx->pdev, vdev_id) 322 #endif 323 ) { 324 populate_mdie(mac_ctx, &frm->MobilityDomain, 325 pe_session->pLimReAssocReq->bssDescription.mdie); 326 } 327 if (pe_session->vhtCapability && 328 pe_session->vhtCapabilityPresentInBeacon) { 329 pe_debug("Populate VHT IEs in Re-Assoc Request"); 330 populate_dot11f_vht_caps(mac_ctx, pe_session, &frm->VHTCaps); 331 vht_enabled = true; 332 populate_dot11f_ext_cap(mac_ctx, vht_enabled, &frm->ExtCap, 333 pe_session); 334 } 335 if (!vht_enabled && 336 pe_session->is_vendor_specific_vhtcaps) { 337 pe_debug("Populate Vendor VHT IEs in Re-Assoc Request"); 338 frm->vendor_vht_ie.present = 1; 339 frm->vendor_vht_ie.sub_type = 340 pe_session->vendor_specific_vht_ie_sub_type; 341 frm->vendor_vht_ie.VHTCaps.present = 1; 342 populate_dot11f_vht_caps(mac_ctx, pe_session, 343 &frm->vendor_vht_ie.VHTCaps); 344 vht_enabled = true; 345 } 346 347 if (lim_is_session_he_capable(pe_session)) { 348 pe_debug("Populate HE IEs"); 349 populate_dot11f_he_caps(mac_ctx, pe_session, 350 &frm->he_cap); 351 populate_dot11f_he_6ghz_cap(mac_ctx, pe_session, 352 &frm->he_6ghz_band_cap); 353 } 354 /* 355 * Extcap IE now support variable length, merge Extcap IE from addn_ie 356 * may change the frame size. Therefore, MUST merge ExtCap IE before 357 * dot11f get packed payload size. 358 */ 359 if (extr_ext_flag) 360 lim_merge_extcap_struct(&frm->ExtCap, &extr_ext_cap, true); 361 362 /* Clear the bits in EXTCAP IE if AP not advertise it in beacon */ 363 if (frm->ExtCap.present && pe_session->is_ext_caps_present) { 364 ie_offset = DOT11F_FF_TIMESTAMP_LEN + 365 DOT11F_FF_BEACONINTERVAL_LEN + 366 DOT11F_FF_CAPABILITIES_LEN; 367 368 qdf_mem_zero((uint8_t *)&bcn_ext_cap, sizeof(tDot11fIEExtCap)); 369 if (pe_session->beacon && (pe_session->bcnLen > 370 (ie_offset + sizeof(struct wlan_frame_hdr)))) { 371 bcn_ie = pe_session->beacon + ie_offset + 372 sizeof(struct wlan_frame_hdr); 373 bcn_ie_len = pe_session->bcnLen - ie_offset - 374 sizeof(struct wlan_frame_hdr); 375 p_ext_cap = (uint8_t *)wlan_get_ie_ptr_from_eid( 376 DOT11F_EID_EXTCAP, 377 bcn_ie, bcn_ie_len); 378 lim_update_extcap_struct(mac_ctx, p_ext_cap, 379 &bcn_ext_cap); 380 lim_merge_extcap_struct(&frm->ExtCap, &bcn_ext_cap, 381 false); 382 } 383 /* 384 * TWT extended capabilities should be populated after the 385 * intersection of beacon caps and self caps is done because 386 * the bits for TWT are unique to STA and AP and cannot be 387 * intersected. 388 */ 389 populate_dot11f_twt_extended_caps(mac_ctx, pe_session, 390 &frm->ExtCap); 391 } 392 393 /* 394 * Do unpack to populate the add_ie buffer to frm structure 395 * before packing the frm structure. In this way, the IE ordering 396 * which the latest 802.11 spec mandates is maintained. 397 */ 398 if (add_ie_len) { 399 ret = dot11f_unpack_re_assoc_request(mac_ctx, add_ie, 400 add_ie_len, 401 frm, true); 402 if (DOT11F_FAILED(ret)) { 403 pe_err("unpack failed, ret: 0x%x", ret); 404 goto end; 405 } 406 } 407 408 if (lim_is_session_eht_capable(pe_session)) { 409 pe_debug("Populate EHT IEs"); 410 populate_dot11f_eht_caps(mac_ctx, pe_session, &frm->eht_cap); 411 } 412 413 status = dot11f_get_packed_re_assoc_request_size(mac_ctx, frm, 414 &payload); 415 if (DOT11F_FAILED(status)) { 416 pe_err("Failure in size calculation (0x%08x)", status); 417 /* We'll fall back on the worst case scenario: */ 418 payload = sizeof(tDot11fReAssocRequest); 419 } else if (DOT11F_WARNED(status)) { 420 pe_warn("Warnings in size calculation (0x%08x)", status); 421 } 422 423 bytes = payload + sizeof(tSirMacMgmtHdr); 424 425 pe_debug("FT IE Reassoc Req %d", 426 mlme_priv->connect_info.ft_info.reassoc_ie_len); 427 428 if (pe_session->is11Rconnection) 429 ft_ies_length = mlme_priv->connect_info.ft_info.reassoc_ie_len; 430 431 qdf_status = cds_packet_alloc((uint16_t) bytes + ft_ies_length, 432 (void **)&frame, (void **)&packet); 433 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 434 pe_session->limMlmState = pe_session->limPrevMlmState; 435 MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_MLM_STATE, 436 pe_session->peSessionId, 437 pe_session->limMlmState)); 438 pe_err("Failed to alloc memory %d", bytes); 439 goto end; 440 } 441 /* Paranoia: */ 442 qdf_mem_zero(frame, bytes + ft_ies_length); 443 444 pe_debug("BSSID: "QDF_MAC_ADDR_FMT, 445 QDF_MAC_ADDR_REF(pe_session->limReAssocbssId)); 446 /* Next, we fill out the buffer descriptor: */ 447 lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME, 448 SIR_MAC_MGMT_REASSOC_REQ, pe_session->limReAssocbssId, 449 pe_session->self_mac_addr); 450 mac_hdr = (tpSirMacMgmtHdr) frame; 451 /* That done, pack the ReAssoc Request: */ 452 status = dot11f_pack_re_assoc_request(mac_ctx, frm, frame + 453 sizeof(tSirMacMgmtHdr), 454 payload, &payload); 455 if (DOT11F_FAILED(status)) { 456 pe_err("Failure in pack (0x%08x)", status); 457 cds_packet_free((void *)packet); 458 goto end; 459 } else if (DOT11F_WARNED(status)) { 460 pe_warn("Warnings in pack (0x%08x)", status); 461 } 462 463 pe_debug("*** Sending Re-Assoc Request length: %d %d to", 464 bytes, payload); 465 466 if (pe_session->is11Rconnection && 467 mlme_priv->connect_info.ft_info.reassoc_ie_len) { 468 int i = 0; 469 470 body = frame + bytes; 471 for (i = 0; i < ft_ies_length; i++) { 472 *body = 473 mlme_priv->connect_info.ft_info.reassoc_ft_ie[i]; 474 body++; 475 } 476 payload += ft_ies_length; 477 } 478 pe_debug("Re-assoc Req Frame is:"); 479 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, 480 (uint8_t *) frame, (bytes + ft_ies_length)); 481 482 if ((pe_session->ftPEContext.pFTPreAuthReq) && 483 (!wlan_reg_is_24ghz_ch_freq( 484 pe_session->ftPEContext.pFTPreAuthReq->pre_auth_channel_freq))) 485 tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; 486 else if (wlan_reg_is_5ghz_ch_freq(pe_session->curr_op_freq) || 487 pe_session->opmode == QDF_P2P_CLIENT_MODE || 488 pe_session->opmode == QDF_P2P_GO_MODE) 489 tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; 490 491 if (pe_session->assoc_req) { 492 qdf_mem_free(pe_session->assoc_req); 493 pe_session->assoc_req = NULL; 494 pe_session->assocReqLen = 0; 495 } 496 497 pe_session->assoc_req = qdf_mem_malloc(payload); 498 if (pe_session->assoc_req) { 499 /* 500 * Store the Assoc request. This is sent to csr/hdd in 501 * join cnf response. 502 */ 503 qdf_mem_copy(pe_session->assoc_req, 504 frame + sizeof(tSirMacMgmtHdr), payload); 505 pe_session->assocReqLen = payload; 506 } 507 508 MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, 509 pe_session->peSessionId, mac_hdr->fc.subType)); 510 lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_REASSOC_START_EVENT, 511 pe_session, QDF_STATUS_SUCCESS, QDF_STATUS_SUCCESS); 512 lim_diag_mgmt_tx_event_report(mac_ctx, mac_hdr, 513 pe_session, QDF_STATUS_SUCCESS, QDF_STATUS_SUCCESS); 514 qdf_status = wma_tx_frame(mac_ctx, packet, 515 (uint16_t) (bytes + ft_ies_length), 516 TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7, 517 lim_tx_complete, frame, tx_flag, vdev_id, 518 0, RATEID_DEFAULT, 0); 519 MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, 520 pe_session->peSessionId, qdf_status)); 521 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 522 pe_err("Failed to send Re-Assoc Request: %X!", qdf_status); 523 } 524 525 end: 526 qdf_mem_free(frm); 527 err: 528 /* Free up buffer allocated for mlmAssocReq */ 529 qdf_mem_free(mlm_reassoc_req); 530 pe_session->pLimMlmReassocReq = NULL; 531 532 } 533 534 /** 535 * lim_send_retry_reassoc_req_frame() - Retry for reassociation 536 * @mac: Global MAC Context 537 * @pMlmReassocReq: Request buffer to be sent 538 * @pe_session: PE Session 539 * 540 * Return: None 541 */ lim_send_retry_reassoc_req_frame(struct mac_context * mac,tLimMlmReassocReq * pMlmReassocReq,struct pe_session * pe_session)542 void lim_send_retry_reassoc_req_frame(struct mac_context *mac, 543 tLimMlmReassocReq *pMlmReassocReq, 544 struct pe_session *pe_session) 545 { 546 tLimMlmReassocCnf mlmReassocCnf; /* keep sme */ 547 tLimMlmReassocReq *pTmpMlmReassocReq = NULL; 548 549 if (!pTmpMlmReassocReq) { 550 pTmpMlmReassocReq = qdf_mem_malloc(sizeof(tLimMlmReassocReq)); 551 if (!pTmpMlmReassocReq) 552 goto end; 553 qdf_mem_copy(pTmpMlmReassocReq, pMlmReassocReq, 554 sizeof(tLimMlmReassocReq)); 555 } 556 /* Prepare and send Reassociation request frame */ 557 /* start reassoc timer. */ 558 mac->lim.lim_timers.gLimReassocFailureTimer.sessionId = 559 pe_session->peSessionId; 560 /* Start reassociation failure timer */ 561 MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TIMER_ACTIVATE, 562 pe_session->peSessionId, eLIM_REASSOC_FAIL_TIMER)); 563 if (tx_timer_activate(&mac->lim.lim_timers.gLimReassocFailureTimer) 564 != TX_SUCCESS) { 565 /* Could not start reassoc failure timer. */ 566 /* Log error */ 567 pe_err("could not start Reassociation failure timer"); 568 /* Return Reassoc confirm with */ 569 /* Resources Unavailable */ 570 mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; 571 mlmReassocCnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE; 572 goto end; 573 } 574 575 lim_send_reassoc_req_with_ft_ies_mgmt_frame(mac, pTmpMlmReassocReq, 576 pe_session); 577 return; 578 579 end: 580 /* Free up buffer allocated for reassocReq */ 581 if (pMlmReassocReq) { 582 qdf_mem_free(pMlmReassocReq); 583 pMlmReassocReq = NULL; 584 } 585 if (pTmpMlmReassocReq) { 586 qdf_mem_free(pTmpMlmReassocReq); 587 pTmpMlmReassocReq = NULL; 588 } 589 mlmReassocCnf.resultCode = eSIR_SME_FT_REASSOC_FAILURE; 590 mlmReassocCnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE; 591 /* Update PE session Id */ 592 mlmReassocCnf.sessionId = pe_session->peSessionId; 593 594 lim_post_sme_message(mac, LIM_MLM_REASSOC_CNF, 595 (uint32_t *) &mlmReassocCnf); 596 } 597 598 /** 599 * lim_send_reassoc_req_mgmt_frame() - Send the reassociation frame 600 * @mac: Global MAC Context 601 * @pMlmReassocReq: Reassociation request buffer to be sent 602 * @pe_session: PE Session 603 * 604 * Return: None 605 */ lim_send_reassoc_req_mgmt_frame(struct mac_context * mac,tLimMlmReassocReq * pMlmReassocReq,struct pe_session * pe_session)606 void lim_send_reassoc_req_mgmt_frame(struct mac_context *mac, 607 tLimMlmReassocReq *pMlmReassocReq, 608 struct pe_session *pe_session) 609 { 610 tDot11fReAssocRequest *frm; 611 uint16_t caps; 612 uint8_t *pFrame; 613 uint32_t nBytes, nPayload, nStatus; 614 uint8_t fQosEnabled, fWmeEnabled, fWsmEnabled; 615 void *pPacket; 616 QDF_STATUS qdf_status; 617 uint16_t nAddIELen; 618 uint8_t *pAddIE; 619 const uint8_t *wpsIe = NULL; 620 uint8_t txFlag = 0; 621 uint8_t PowerCapsPopulated = false; 622 uint8_t smeSessionId = 0; 623 bool isVHTEnabled = false; 624 tpSirMacMgmtHdr pMacHdr; 625 int ret; 626 tDot11fIEExtCap extr_ext_cap; 627 QDF_STATUS sir_status; 628 bool extr_ext_flag = true; 629 uint32_t ie_offset = 0; 630 tDot11fIEExtCap bcn_ext_cap; 631 uint8_t *bcn_ie = NULL; 632 uint32_t bcn_ie_len = 0; 633 uint8_t *p_ext_cap = NULL; 634 enum rateid min_rid = RATEID_DEFAULT; 635 636 if (!pe_session) 637 return; 638 639 smeSessionId = pe_session->smeSessionId; 640 if (!pe_session->pLimReAssocReq) 641 return; 642 643 frm = qdf_mem_malloc(sizeof(*frm)); 644 if (!frm) 645 goto err; 646 nAddIELen = pe_session->pLimReAssocReq->addIEAssoc.length; 647 pAddIE = pe_session->pLimReAssocReq->addIEAssoc.addIEdata; 648 649 qdf_mem_zero((uint8_t *) frm, sizeof(*frm)); 650 651 if (nAddIELen && pe_session->is_ext_caps_present) { 652 qdf_mem_zero((uint8_t *)&extr_ext_cap, 653 sizeof(tDot11fIEExtCap)); 654 sir_status = lim_strip_extcap_update_struct( 655 mac, pAddIE, &nAddIELen, &extr_ext_cap); 656 if (QDF_STATUS_SUCCESS != sir_status) { 657 extr_ext_flag = false; 658 pe_debug("Unable to Stripoff ExtCap IE from Assoc Req"); 659 } else { 660 struct s_ext_cap *p_ext_cap = (struct s_ext_cap *) 661 extr_ext_cap.bytes; 662 663 if (p_ext_cap->interworking_service) 664 p_ext_cap->qos_map = 1; 665 extr_ext_cap.num_bytes = 666 lim_compute_ext_cap_ie_length(&extr_ext_cap); 667 extr_ext_flag = (extr_ext_cap.num_bytes > 0); 668 } 669 } else { 670 pe_debug("No addn IE or peer doesn't support addnIE for Assoc Req"); 671 extr_ext_flag = false; 672 } 673 674 caps = pMlmReassocReq->capabilityInfo; 675 #if defined(FEATURE_WLAN_WAPI) 676 /* 677 * CR: 262463 : 678 * According to WAPI standard: 679 * 7.3.1.4 Capability Information field 680 * In WAPI, non-AP STAs within an ESS set the Privacy subfield to 0 in 681 * transmitted. Association or Reassociation management frames. APs 682 * ignore the Privacy subfield within received Association and 683 * Reassociation management frames. 684 */ 685 if (pe_session->encryptType == eSIR_ED_WPI) 686 ((tSirMacCapabilityInfo *) &caps)->privacy = 0; 687 #endif 688 swap_bit_field16(caps, (uint16_t *) &frm->Capabilities); 689 690 frm->ListenInterval.interval = pMlmReassocReq->listenInterval; 691 692 qdf_mem_copy((uint8_t *) frm->CurrentAPAddress.mac, 693 (uint8_t *) pe_session->bssId, 6); 694 695 populate_dot11f_ssid2(pe_session, &frm->SSID); 696 populate_dot11f_supp_rates(mac, POPULATE_DOT11F_RATES_OPERATIONAL, 697 &frm->SuppRates, pe_session); 698 699 fQosEnabled = (pe_session->limQosEnabled) && 700 SIR_MAC_GET_QOS(pe_session->limReassocBssCaps); 701 702 fWmeEnabled = (pe_session->limWmeEnabled) && 703 LIM_BSS_CAPS_GET(WME, pe_session->limReassocBssQosCaps); 704 705 fWsmEnabled = (pe_session->limWsmEnabled) && fWmeEnabled && 706 LIM_BSS_CAPS_GET(WSM, pe_session->limReassocBssQosCaps); 707 708 if (pe_session->lim11hEnable && 709 pe_session->spectrumMgtEnabled) { 710 PowerCapsPopulated = true; 711 populate_dot11f_power_caps(mac, &frm->PowerCaps, LIM_REASSOC, 712 pe_session); 713 populate_dot11f_supp_channels(mac, &frm->SuppChannels, 714 LIM_REASSOC, pe_session); 715 } 716 if (mac->rrm.rrmPEContext.rrmEnable && 717 SIR_MAC_GET_RRM(pe_session->limCurrentBssCaps)) { 718 if (PowerCapsPopulated == false) { 719 PowerCapsPopulated = true; 720 populate_dot11f_power_caps(mac, &frm->PowerCaps, 721 LIM_REASSOC, pe_session); 722 } 723 } 724 725 if (fQosEnabled) 726 populate_dot11f_qos_caps_station(mac, pe_session, 727 &frm->QOSCapsStation); 728 729 populate_dot11f_ext_supp_rates(mac, POPULATE_DOT11F_RATES_OPERATIONAL, 730 &frm->ExtSuppRates, pe_session); 731 732 if (mac->rrm.rrmPEContext.rrmEnable && 733 SIR_MAC_GET_RRM(pe_session->limCurrentBssCaps)) 734 populate_dot11f_rrm_ie(mac, &frm->RRMEnabledCap, pe_session); 735 /* The join request *should* contain zero or one of the WPA and RSN */ 736 /* IEs. The payload send along with the request is a */ 737 /* 'struct join_req'; the IE portion is held inside a 'tSirRSNie': */ 738 739 /* typedef struct sSirRSNie */ 740 /* { */ 741 /* uint16_t length; */ 742 /* uint8_t rsnIEdata[WLAN_MAX_IE_LEN+2]; */ 743 /* } tSirRSNie, *tpSirRSNie; */ 744 745 /* So, we should be able to make the following two calls harmlessly, */ 746 /* since they do nothing if they don't find the given IE in the */ 747 /* bytestream with which they're provided. */ 748 749 /* The net effect of this will be to faithfully transmit whatever */ 750 /* security IE is in the join request. */ 751 752 /**However*, if we're associating for the purpose of WPS */ 753 /* enrollment, and we've been configured to indicate that by */ 754 /* eliding the WPA or RSN IE, we just skip this: */ 755 if (nAddIELen && pAddIE) 756 wpsIe = limGetWscIEPtr(mac, pAddIE, nAddIELen); 757 if (!wpsIe) { 758 populate_dot11f_rsn_opaque(mac, 759 &(pe_session->pLimReAssocReq->rsnIE), 760 &frm->RSNOpaque); 761 populate_dot11f_wpa_opaque(mac, 762 &(pe_session->pLimReAssocReq->rsnIE), 763 &frm->WPAOpaque); 764 #if defined(FEATURE_WLAN_WAPI) 765 populate_dot11f_wapi_opaque(mac, 766 &(pe_session->pLimReAssocReq-> 767 rsnIE), &frm->WAPIOpaque); 768 #endif /* defined(FEATURE_WLAN_WAPI) */ 769 } 770 /* include WME EDCA IE as well */ 771 if (fWmeEnabled) { 772 populate_dot11f_wmm_info_station_per_session(mac, 773 pe_session, &frm->WMMInfoStation); 774 775 if (fWsmEnabled) 776 populate_dot11f_wmm_caps(&frm->WMMCaps); 777 } 778 779 if (pe_session->htCapability && 780 mac->lim.htCapabilityPresentInBeacon) { 781 populate_dot11f_ht_caps(mac, pe_session, &frm->HTCaps); 782 } 783 if (pe_session->vhtCapability && 784 pe_session->vhtCapabilityPresentInBeacon) { 785 pe_warn("Populate VHT IEs in Re-Assoc Request"); 786 populate_dot11f_vht_caps(mac, pe_session, &frm->VHTCaps); 787 isVHTEnabled = true; 788 } 789 populate_dot11f_ext_cap(mac, isVHTEnabled, &frm->ExtCap, pe_session); 790 791 if (lim_is_session_he_capable(pe_session)) { 792 pe_debug("Populate HE IEs"); 793 populate_dot11f_he_caps(mac, pe_session, 794 &frm->he_cap); 795 populate_dot11f_he_6ghz_cap(mac, pe_session, 796 &frm->he_6ghz_band_cap); 797 } 798 799 if (lim_is_session_eht_capable(pe_session)) { 800 pe_debug("Populate EHT IEs"); 801 populate_dot11f_eht_caps(mac, pe_session, &frm->eht_cap); 802 } 803 /* 804 * Extcap IE now support variable length, merge Extcap IE from addn_ie 805 * may change the frame size. Therefore, MUST merge ExtCap IE before 806 * dot11f get packed payload size. 807 */ 808 if (extr_ext_flag) 809 lim_merge_extcap_struct(&frm->ExtCap, &extr_ext_cap, true); 810 811 /* Clear the bits in EXTCAP IE if AP not advertise it in beacon */ 812 if (frm->ExtCap.present && pe_session->is_ext_caps_present) { 813 ie_offset = DOT11F_FF_TIMESTAMP_LEN + 814 DOT11F_FF_BEACONINTERVAL_LEN + 815 DOT11F_FF_CAPABILITIES_LEN; 816 817 qdf_mem_zero((uint8_t *)&bcn_ext_cap, sizeof(tDot11fIEExtCap)); 818 if (pe_session->beacon && (pe_session->bcnLen > 819 (ie_offset + sizeof(struct wlan_frame_hdr)))) { 820 bcn_ie = pe_session->beacon + ie_offset + 821 sizeof(struct wlan_frame_hdr); 822 bcn_ie_len = pe_session->bcnLen - ie_offset - 823 sizeof(struct wlan_frame_hdr); 824 p_ext_cap = (uint8_t *)wlan_get_ie_ptr_from_eid( 825 DOT11F_EID_EXTCAP, 826 bcn_ie, bcn_ie_len); 827 lim_update_extcap_struct(mac, p_ext_cap, 828 &bcn_ext_cap); 829 lim_merge_extcap_struct(&frm->ExtCap, &bcn_ext_cap, 830 false); 831 } 832 /* 833 * TWT extended capabilities should be populated after the 834 * intersection of beacon caps and self caps is done because 835 * the bits for TWT are unique to STA and AP and cannot be 836 * intersected. 837 */ 838 populate_dot11f_twt_extended_caps(mac, pe_session, 839 &frm->ExtCap); 840 } 841 842 /* 843 * Do unpack to populate the add_ie buffer to frm structure 844 * before packing the frm structure. In this way, the IE ordering 845 * which the latest 802.11 spec mandates is maintained. 846 */ 847 if (nAddIELen) { 848 ret = dot11f_unpack_re_assoc_request(mac, pAddIE, nAddIELen, 849 frm, true); 850 if (DOT11F_FAILED(ret)) { 851 pe_err("unpack failed, ret: 0x%x", ret); 852 goto end; 853 } 854 } 855 856 nStatus = 857 dot11f_get_packed_re_assoc_request_size(mac, frm, &nPayload); 858 if (DOT11F_FAILED(nStatus)) { 859 pe_err("Fail to get size:ReassocReq: (0x%08x)", nStatus); 860 /* We'll fall back on the worst case scenario: */ 861 nPayload = sizeof(tDot11fReAssocRequest); 862 } else if (DOT11F_WARNED(nStatus)) { 863 pe_err("warning for size:ReAssoc Req: (0x%08x)", nStatus); 864 } 865 866 nBytes = nPayload + sizeof(tSirMacMgmtHdr); 867 868 qdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, 869 (void **)&pPacket); 870 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 871 pe_session->limMlmState = pe_session->limPrevMlmState; 872 MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_MLM_STATE, 873 pe_session->peSessionId, 874 pe_session->limMlmState)); 875 pe_err("Failed to alloc %d bytes for a ReAssociation Req", 876 nBytes); 877 goto end; 878 } 879 /* Paranoia: */ 880 qdf_mem_zero(pFrame, nBytes); 881 882 /* Next, we fill out the buffer descriptor: */ 883 lim_populate_mac_header(mac, pFrame, SIR_MAC_MGMT_FRAME, 884 SIR_MAC_MGMT_REASSOC_REQ, pe_session->limReAssocbssId, 885 pe_session->self_mac_addr); 886 pMacHdr = (tpSirMacMgmtHdr) pFrame; 887 888 /* That done, pack the Probe Request: */ 889 nStatus = dot11f_pack_re_assoc_request(mac, frm, pFrame + 890 sizeof(tSirMacMgmtHdr), 891 nPayload, &nPayload); 892 if (DOT11F_FAILED(nStatus)) { 893 pe_err("Fail to pack a Re-Assoc Req: (0x%08x)", nStatus); 894 cds_packet_free((void *)pPacket); 895 goto end; 896 } else if (DOT11F_WARNED(nStatus)) { 897 pe_warn("warning packing a Re-AssocReq: (0x%08x)", nStatus); 898 } 899 900 lim_cp_stats_cstats_log_assoc_req_evt(pe_session, CSTATS_DIR_TX, 901 pMacHdr->bssId, pMacHdr->sa, 902 frm->SSID.num_ssid, 903 frm->SSID.ssid, 904 frm->HTCaps.present, 905 frm->VHTCaps.present, 906 frm->he_cap.present, 907 frm->eht_cap.present, true); 908 909 pe_debug("*** Sending Re-Association Request length: %d" "to", nBytes); 910 911 if (pe_session->assoc_req) { 912 qdf_mem_free(pe_session->assoc_req); 913 pe_session->assoc_req = NULL; 914 pe_session->assocReqLen = 0; 915 } 916 917 pe_session->assoc_req = qdf_mem_malloc(nPayload); 918 if (pe_session->assoc_req) { 919 /* Store the Assocrequest. It is sent to csr in joincnfrsp */ 920 qdf_mem_copy(pe_session->assoc_req, 921 pFrame + sizeof(tSirMacMgmtHdr), nPayload); 922 pe_session->assocReqLen = nPayload; 923 } 924 925 if (wlan_reg_is_5ghz_ch_freq(pe_session->curr_op_freq) || 926 pe_session->opmode == QDF_P2P_CLIENT_MODE || 927 pe_session->opmode == QDF_P2P_GO_MODE) 928 txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; 929 930 if (pe_session->opmode == QDF_P2P_CLIENT_MODE || 931 pe_session->opmode == QDF_STA_MODE) 932 txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK; 933 934 MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, 935 pe_session->peSessionId, pMacHdr->fc.subType)); 936 lim_diag_event_report(mac, WLAN_PE_DIAG_REASSOC_START_EVENT, 937 pe_session, QDF_STATUS_SUCCESS, QDF_STATUS_SUCCESS); 938 lim_diag_mgmt_tx_event_report(mac, pMacHdr, 939 pe_session, QDF_STATUS_SUCCESS, 940 QDF_STATUS_SUCCESS); 941 942 if (pe_session->is_oui_auth_assoc_6mbps_2ghz_enable) 943 min_rid = RATEID_6MBPS; 944 945 qdf_status = 946 wma_tx_frame(mac, pPacket, 947 (uint16_t) (sizeof(tSirMacMgmtHdr) + nPayload), 948 TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7, 949 lim_tx_complete, pFrame, txFlag, smeSessionId, 0, 950 min_rid, 0); 951 MTRACE(qdf_trace 952 (QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, 953 pe_session->peSessionId, qdf_status)); 954 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 955 pe_err("Failed to send Re-Association Request: %X!", 956 qdf_status); 957 /* Pkt will be freed up by the callback */ 958 } 959 960 end: 961 qdf_mem_free(frm); 962 err: 963 /* Free up buffer allocated for mlmAssocReq */ 964 qdf_mem_free(pMlmReassocReq); 965 pe_session->pLimMlmReassocReq = NULL; 966 967 } 968 lim_process_rx_scan_handler(struct wlan_objmgr_vdev * vdev,struct scan_event * event,void * arg)969 void lim_process_rx_scan_handler(struct wlan_objmgr_vdev *vdev, 970 struct scan_event *event, 971 void *arg) 972 { 973 struct mac_context *mac_ctx; 974 enum sir_scan_event_type event_type; 975 976 pe_debug("event: %u, id: 0x%x, requestor: 0x%x, freq: %u, reason: %u", 977 event->type, event->scan_id, event->requester, 978 event->chan_freq, event->reason); 979 980 mac_ctx = (struct mac_context *)arg; 981 event_type = 0x1 << event->type; 982 983 qdf_mtrace(QDF_MODULE_ID_SCAN, QDF_MODULE_ID_PE, event->type, 984 event->vdev_id, event->scan_id); 985 986 switch (event_type) { 987 case SIR_SCAN_EVENT_STARTED: 988 break; 989 case SIR_SCAN_EVENT_COMPLETED: 990 pe_debug("No.of beacons and probe response received per scan %d", 991 mac_ctx->lim.beacon_probe_rsp_cnt_per_scan); 992 fallthrough; 993 case SIR_SCAN_EVENT_FOREIGN_CHANNEL: 994 case SIR_SCAN_EVENT_START_FAILED: 995 if ((mac_ctx->lim.req_id | PREAUTH_REQUESTOR_ID) == 996 event->requester) 997 lim_preauth_scan_event_handler(mac_ctx, 998 event_type, 999 event->vdev_id, 1000 event->scan_id); 1001 break; 1002 case SIR_SCAN_EVENT_BSS_CHANNEL: 1003 case SIR_SCAN_EVENT_DEQUEUED: 1004 case SIR_SCAN_EVENT_PREEMPTED: 1005 default: 1006 pe_debug("Received unhandled scan event %u", event_type); 1007 } 1008 } 1009