1 /* 2 * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-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 * This file lim_process_assoc_req_frame.c contains the code 22 * for processing Re/Association Request Frame. 23 */ 24 #include "cds_api.h" 25 #include "ani_global.h" 26 #include "wni_cfg.h" 27 #include "sir_api.h" 28 #include "cfg_ucfg_api.h" 29 30 #include "sch_api.h" 31 #include "utils_api.h" 32 #include "lim_types.h" 33 #include "lim_utils.h" 34 #include "lim_assoc_utils.h" 35 #include "lim_security_utils.h" 36 #include "lim_ser_des_utils.h" 37 #include "lim_admit_control.h" 38 #include "cds_packet.h" 39 #include "lim_session_utils.h" 40 #include "utils_parser.h" 41 #include "wlan_p2p_api.h" 42 43 #include "qdf_types.h" 44 #include "cds_utils.h" 45 #include "wlan_utility.h" 46 #include "wlan_crypto_global_api.h" 47 #include "lim_mlo.h" 48 #include <son_api.h> 49 50 /** 51 * lim_convert_supported_channels - Parses channel support IE 52 * @mac_ctx: A pointer to Global MAC structure 53 * @assoc_ind: A pointer to SME ASSOC/REASSOC IND 54 * @assoc_req: A pointer to ASSOC/REASSOC Request frame 55 * 56 * This function is called by lim_process_assoc_req_frame() to 57 * parse the channel support IE in the Assoc/Reassoc Request 58 * frame, and send relevant information in the SME_ASSOC_IND 59 * 60 * Return: None 61 */ lim_convert_supported_channels(struct mac_context * mac_ctx,tpLimMlmAssocInd assoc_ind,tSirAssocReq * assoc_req)62 static void lim_convert_supported_channels(struct mac_context *mac_ctx, 63 tpLimMlmAssocInd assoc_ind, 64 tSirAssocReq *assoc_req) 65 { 66 uint16_t i, j, index = 0; 67 uint8_t first_ch_no; 68 uint8_t chn_count; 69 uint8_t next_ch_no; 70 uint8_t channel_offset = 0; 71 uint32_t chan_freq; 72 73 if (assoc_req->supportedChannels.length >= 74 SIR_MAX_SUPPORTED_CHANNEL_LIST) { 75 pe_err("Number of supported channels: %d is more than MAX", 76 assoc_req->supportedChannels.length); 77 assoc_ind->supportedChannels.numChnl = 0; 78 return; 79 } 80 81 for (i = 0; i < (assoc_req->supportedChannels.length); i++) { 82 /* Get First Channel Number */ 83 first_ch_no = assoc_req->supportedChannels.supportedChannels[i]; 84 assoc_ind->supportedChannels.channelList[index] = first_ch_no; 85 i++; 86 index++; 87 88 /* Get Number of Channels in a Subband */ 89 chn_count = assoc_req->supportedChannels.supportedChannels[i]; 90 if (index >= SIR_MAX_SUPPORTED_CHANNEL_LIST) { 91 pe_warn("Ch count > max supported: %d", chn_count); 92 assoc_ind->supportedChannels.numChnl = 0; 93 return; 94 } 95 if (chn_count <= 1) 96 continue; 97 next_ch_no = first_ch_no; 98 chan_freq = wlan_reg_legacy_chan_to_freq(mac_ctx->pdev, 99 first_ch_no); 100 101 if (REG_BAND_5G == lim_get_rf_band(chan_freq)) 102 channel_offset = SIR_11A_FREQUENCY_OFFSET; 103 else if (REG_BAND_2G == lim_get_rf_band(chan_freq)) 104 channel_offset = SIR_11B_FREQUENCY_OFFSET; 105 else 106 continue; 107 108 for (j = 1; j < chn_count; j++) { 109 next_ch_no += channel_offset; 110 assoc_ind->supportedChannels.channelList[index] 111 = next_ch_no; 112 index++; 113 if (index >= SIR_MAX_SUPPORTED_CHANNEL_LIST) { 114 pe_warn("Ch count > supported: %d", chn_count); 115 assoc_ind->supportedChannels.numChnl = 0; 116 return; 117 } 118 } 119 } 120 121 assoc_ind->supportedChannels.numChnl = (uint8_t) index; 122 pe_debug("Send AssocInd to WSM: minPwr: %d maxPwr: %d numChnl: %d", 123 assoc_ind->powerCap.minTxPower, 124 assoc_ind->powerCap.maxTxPower, 125 assoc_ind->supportedChannels.numChnl); 126 127 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, 128 assoc_req->supportedChannels.supportedChannels, 129 assoc_req->supportedChannels.length); 130 } 131 132 /** 133 * lim_check_sta_in_pe_entries() - checks if sta exists in any dph tables. 134 * @mac_ctx: Pointer to Global MAC structure 135 * @sa: Mac address of requesting peer 136 * @sessionid - session id for which session is initiated 137 * @dup_entry: pointer for duplicate entry found 138 * 139 * This function is called by lim_process_assoc_req_frame() to check if STA 140 * entry already exists in any of the PE entries of the AP. If it exists, deauth 141 * will be sent on that session and the STA deletion will happen. After this, 142 * the ASSOC request will be processed. If the STA is already in deleting phase 143 * this will return failure so that assoc req will be rejected till STA is 144 * deleted. 145 * 146 * Return: QDF_STATUS. 147 */ lim_check_sta_in_pe_entries(struct mac_context * mac_ctx,tSirMacAddr sa,uint16_t sessionid,bool * dup_entry)148 static QDF_STATUS lim_check_sta_in_pe_entries(struct mac_context *mac_ctx, 149 tSirMacAddr sa, 150 uint16_t sessionid, 151 bool *dup_entry) 152 { 153 uint8_t i; 154 uint16_t assoc_id = 0; 155 tpDphHashNode sta_ds = NULL; 156 struct pe_session *session; 157 158 *dup_entry = false; 159 for (i = 0; i < mac_ctx->lim.maxBssId; i++) { 160 session = &mac_ctx->lim.gpSession[i]; 161 if (session->valid && 162 (session->opmode == QDF_SAP_MODE)) { 163 sta_ds = dph_lookup_hash_entry( 164 mac_ctx, sa, 165 &assoc_id, &session->dph.dphHashTable); 166 if (sta_ds 167 && (!sta_ds->rmfEnabled || 168 (sessionid != session->peSessionId)) 169 ) { 170 if (sta_ds->mlmStaContext.mlmState == 171 eLIM_MLM_WT_DEL_STA_RSP_STATE || 172 sta_ds->mlmStaContext.mlmState == 173 eLIM_MLM_WT_DEL_BSS_RSP_STATE || 174 sta_ds->sta_deletion_in_progress) { 175 pe_debug( 176 "Deletion is in progress (%d) for peer:"QDF_MAC_ADDR_FMT" in mlmState %d", 177 sta_ds->sta_deletion_in_progress, 178 QDF_MAC_ADDR_REF(sta_ds->staAddr), 179 sta_ds->mlmStaContext.mlmState); 180 *dup_entry = true; 181 return QDF_STATUS_E_AGAIN; 182 } 183 sta_ds->sta_deletion_in_progress = true; 184 pe_err("Sending Disassoc and Deleting existing STA entry:" 185 QDF_MAC_ADDR_FMT, 186 QDF_MAC_ADDR_REF( 187 session->self_mac_addr)); 188 lim_send_disassoc_mgmt_frame(mac_ctx, 189 REASON_UNSPEC_FAILURE, 190 (uint8_t *)sa, session, false); 191 /* 192 * Cleanup Rx path posts eWNI_SME_DISASSOC_RSP 193 * msg to SME after delete sta which will update 194 * the userspace with disconnect 195 */ 196 sta_ds->mlmStaContext.cleanupTrigger = 197 eLIM_DUPLICATE_ENTRY; 198 sta_ds->mlmStaContext.disassocReason = 199 REASON_DISASSOC_DUE_TO_INACTIVITY; 200 lim_send_sme_disassoc_ind(mac_ctx, sta_ds, 201 session); 202 *dup_entry = true; 203 break; 204 } 205 } 206 } 207 208 return QDF_STATUS_SUCCESS; 209 } 210 211 /** 212 * lim_chk_sa_da() - checks source addr to destination addr of assoc req frame 213 * @mac_ctx: pointer to Global MAC structure 214 * @hdr: pointer to the MAC head 215 * @session: pointer to pe session entry 216 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 217 * 218 * Checks source addr to destination addr of assoc req frame 219 * 220 * Return: true if source and destination address are different 221 */ lim_chk_sa_da(struct mac_context * mac_ctx,tpSirMacMgmtHdr hdr,struct pe_session * session,uint8_t sub_type)222 static bool lim_chk_sa_da(struct mac_context *mac_ctx, tpSirMacMgmtHdr hdr, 223 struct pe_session *session, uint8_t sub_type) 224 { 225 if (qdf_mem_cmp((uint8_t *) hdr->sa, 226 (uint8_t *) hdr->da, 227 (uint8_t) (sizeof(tSirMacAddr)))) 228 return true; 229 230 pe_err("Assoc Req rejected: wlan.sa = wlan.da"); 231 lim_send_assoc_rsp_mgmt_frame(mac_ctx, STATUS_UNSPECIFIED_FAILURE, 232 1, hdr->sa, sub_type, 0, session, false); 233 return false; 234 } 235 236 /** 237 * lim_chk_assoc_req_parse_error() - checks for error in frame parsing 238 * @mac_ctx: pointer to Global MAC structure 239 * @sa: Mac address of requesting peer 240 * @session: pointer to pe session entry 241 * @assoc_req: pointer to ASSOC/REASSOC Request frame 242 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 243 * @frm_body: frame body 244 * @frame_len: frame len 245 * 246 * Checks for error in frame parsing 247 * 248 * Return: true of no error, false otherwise 249 */ lim_chk_assoc_req_parse_error(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,uint8_t * frm_body,uint32_t frame_len)250 static bool lim_chk_assoc_req_parse_error(struct mac_context *mac_ctx, 251 tSirMacAddr sa, 252 struct pe_session *session, 253 tpSirAssocReq assoc_req, 254 uint8_t sub_type, uint8_t *frm_body, 255 uint32_t frame_len) 256 { 257 QDF_STATUS qdf_status; 258 enum wlan_status_code wlan_status; 259 struct qdf_mac_addr *mld_mac; 260 261 if (sub_type == LIM_ASSOC) 262 wlan_status = sir_convert_assoc_req_frame2_struct(mac_ctx, frm_body, 263 frame_len, 264 assoc_req); 265 else 266 wlan_status = sir_convert_reassoc_req_frame2_struct(mac_ctx, 267 frm_body, frame_len, assoc_req); 268 269 if (wlan_status == STATUS_SUCCESS) { 270 qdf_status = lim_strip_and_decode_eht_cap( 271 frm_body + WLAN_ASSOC_REQ_IES_OFFSET, 272 frame_len - WLAN_ASSOC_REQ_IES_OFFSET, 273 &assoc_req->eht_cap, 274 assoc_req->he_cap, 275 session->curr_op_freq); 276 if (QDF_IS_STATUS_ERROR(qdf_status)) { 277 pe_err("Failed to extract eht cap"); 278 return false; 279 } 280 281 /* 282 * If EHT capability is not present but MLO is parsed 283 * suceesssfully, remove the ML info from assoc request. 284 */ 285 mld_mac = (struct qdf_mac_addr *)assoc_req->mld_mac; 286 if (!assoc_req->eht_cap.present && 287 !qdf_is_macaddr_zero(mld_mac)) { 288 qdf_zero_macaddr(mld_mac); 289 qdf_mem_zero(&assoc_req->mlo_info, 290 sizeof(assoc_req->mlo_info)); 291 } 292 293 return true; 294 } 295 296 pe_warn("Assoc Req rejected: frame parsing error. source addr:" 297 QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(sa)); 298 lim_send_assoc_rsp_mgmt_frame(mac_ctx, wlan_status, 299 1, sa, sub_type, 0, session, false); 300 return false; 301 } 302 303 /** 304 * lim_chk_capab() - checks for capab match 305 * @mac_ctx: pointer to Global MAC structure 306 * @sa: Mac address of requesting peer 307 * @session: pointer to pe session entry 308 * @assoc_req: pointer to ASSOC/REASSOC Request frame 309 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 310 * @local_cap: local capabilities of SAP 311 * 312 * Checks for capab match 313 * 314 * Return: true of no error, false otherwise 315 */ lim_chk_capab(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,tSirMacCapabilityInfo * local_cap)316 static bool lim_chk_capab(struct mac_context *mac_ctx, tSirMacAddr sa, 317 struct pe_session *session, tpSirAssocReq assoc_req, 318 uint8_t sub_type, tSirMacCapabilityInfo *local_cap) 319 { 320 uint16_t temp; 321 322 if (lim_get_capability_info(mac_ctx, &temp, session) != 323 QDF_STATUS_SUCCESS) { 324 pe_err("could not retrieve Capabilities"); 325 return false; 326 } 327 328 lim_copy_u16((uint8_t *) local_cap, temp); 329 330 if (lim_compare_capabilities(mac_ctx, assoc_req, 331 local_cap, session) == false) { 332 pe_warn("Rcvd %s Req with unsupported capab from" 333 QDF_MAC_ADDR_FMT, 334 (LIM_ASSOC == sub_type) ? "Assoc" : "ReAssoc", 335 QDF_MAC_ADDR_REF(sa)); 336 /* 337 * Capabilities of requesting STA does not match with 338 * local capabilities. Respond with 'unsupported capabilities' 339 * status code. 340 */ 341 lim_send_assoc_rsp_mgmt_frame( 342 mac_ctx, STATUS_CAPS_UNSUPPORTED, 343 1, sa, sub_type, 0, session, false); 344 return false; 345 } 346 return true; 347 } 348 349 /** 350 * lim_chk_ssid() - checks for SSID match 351 * @mac_ctx: pointer to Global MAC structure 352 * @sa: Mac address of requesting peer 353 * @session: pointer to pe session entry 354 * @assoc_req: pointer to ASSOC/REASSOC Request frame 355 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 356 * 357 * Checks for SSID match 358 * 359 * Return: true of no error, false otherwise 360 */ lim_chk_ssid(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)361 static bool lim_chk_ssid(struct mac_context *mac_ctx, tSirMacAddr sa, 362 struct pe_session *session, tpSirAssocReq assoc_req, 363 uint8_t sub_type) 364 { 365 if (!lim_cmp_ssid(&assoc_req->ssId, session)) 366 return true; 367 368 pe_err("%s Req with ssid wrong(Rcvd: " QDF_SSID_FMT " self: " QDF_SSID_FMT ") from " QDF_MAC_ADDR_FMT, 369 (LIM_ASSOC == sub_type) ? "Assoc" : "ReAssoc", 370 QDF_SSID_REF(assoc_req->ssId.length, assoc_req->ssId.ssId), 371 QDF_SSID_REF(session->ssId.length, session->ssId.ssId), 372 QDF_MAC_ADDR_REF(sa)); 373 374 /* 375 * Received Re/Association Request with either Broadcast SSID OR with 376 * SSID that does not match with local one. Respond with unspecified 377 * status code. 378 */ 379 lim_send_assoc_rsp_mgmt_frame(mac_ctx, STATUS_UNSPECIFIED_FAILURE, 380 1, sa, sub_type, 0, session, false); 381 return false; 382 } 383 384 /** 385 * lim_chk_rates() - checks for supported rates 386 * @mac_ctx: pointer to Global MAC structure 387 * @sa: Mac address of requesting peer 388 * @session: pointer to pe session entry 389 * @assoc_req: pointer to ASSOC/REASSOC Request frame 390 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 391 * 392 * Checks for supported rates 393 * 394 * Return: true of no error, false otherwise 395 */ lim_chk_rates(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)396 static bool lim_chk_rates(struct mac_context *mac_ctx, tSirMacAddr sa, 397 struct pe_session *session, tpSirAssocReq assoc_req, 398 uint8_t sub_type) 399 { 400 uint8_t i = 0, j = 0; 401 tSirMacRateSet basic_rates; 402 /* 403 * Verify if the requested rates are available in supported rate 404 * set or Extended rate set. Some APs are adding basic rates in 405 * Extended rateset IE 406 */ 407 basic_rates.numRates = 0; 408 409 for (i = 0; i < assoc_req->supportedRates.numRates && 410 (i < SIR_MAC_MAX_NUMBER_OF_RATES); i++) { 411 basic_rates.rate[i] = assoc_req->supportedRates.rate[i]; 412 basic_rates.numRates++; 413 } 414 415 for (j = 0; (j < assoc_req->extendedRates.numRates) && 416 (i < SIR_MAC_MAX_NUMBER_OF_RATES); i++, j++) { 417 basic_rates.rate[i] = assoc_req->extendedRates.rate[j]; 418 basic_rates.numRates++; 419 } 420 421 if (lim_check_rx_basic_rates(mac_ctx, basic_rates, session) == true) 422 return true; 423 424 pe_warn("Assoc Req rejected: unsupported rates, source addr: %s" 425 QDF_MAC_ADDR_FMT, 426 (LIM_ASSOC == sub_type) ? "Assoc" : "ReAssoc", 427 QDF_MAC_ADDR_REF(sa)); 428 /* 429 * Requesting STA does not support ALL BSS basic rates. Respond with 430 * 'basic rates not supported' status code. 431 */ 432 lim_send_assoc_rsp_mgmt_frame( 433 mac_ctx, STATUS_ASSOC_DENIED_RATES, 1, 434 sa, sub_type, 0, session, false); 435 return false; 436 } 437 438 /** 439 * lim_chk_11g_only() - checks for non 11g STA 440 * @mac_ctx: pointer to Global MAC structure 441 * @sa: Mac address of requesting peer 442 * @session: pointer to pe session entry 443 * @assoc_req: pointer to ASSOC/REASSOC Request frame 444 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 445 * 446 * Checks for non 11g STA 447 * 448 * Return: true of no error, false otherwise 449 */ lim_chk_11g_only(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)450 static bool lim_chk_11g_only(struct mac_context *mac_ctx, tSirMacAddr sa, 451 struct pe_session *session, tpSirAssocReq assoc_req, 452 uint8_t sub_type) 453 { 454 if (LIM_IS_AP_ROLE(session) && 455 (session->dot11mode == MLME_DOT11_MODE_11G_ONLY) && 456 (assoc_req->HTCaps.present)) { 457 pe_err("SOFTAP was in 11G only mode, rejecting legacy STA: " 458 QDF_MAC_ADDR_FMT, 459 QDF_MAC_ADDR_REF(sa)); 460 lim_send_assoc_rsp_mgmt_frame( 461 mac_ctx, STATUS_CAPS_UNSUPPORTED, 462 1, sa, sub_type, 0, session, false); 463 return false; 464 } 465 return true; 466 } 467 468 /** 469 * lim_chk_11n_only() - checks for non 11n STA 470 * @mac_ctx: pointer to Global MAC structure 471 * @sa: Mac address of requesting peer 472 * @session: pointer to pe session entry 473 * @assoc_req: pointer to ASSOC/REASSOC Request frame 474 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 475 * 476 * Checks for non 11n STA 477 * 478 * Return: true of no error, false otherwise 479 */ lim_chk_11n_only(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)480 static bool lim_chk_11n_only(struct mac_context *mac_ctx, tSirMacAddr sa, 481 struct pe_session *session, tpSirAssocReq assoc_req, 482 uint8_t sub_type) 483 { 484 if (LIM_IS_AP_ROLE(session) && 485 (session->dot11mode == MLME_DOT11_MODE_11N_ONLY) && 486 (!assoc_req->HTCaps.present)) { 487 pe_err("SOFTAP was in 11N only mode, rejecting legacy STA: " 488 QDF_MAC_ADDR_FMT, 489 QDF_MAC_ADDR_REF(sa)); 490 lim_send_assoc_rsp_mgmt_frame( 491 mac_ctx, STATUS_CAPS_UNSUPPORTED, 492 1, sa, sub_type, 0, session, false); 493 return false; 494 } 495 return true; 496 } 497 498 /** 499 * lim_chk_11ac_only() - checks for non 11ac STA 500 * @mac_ctx: pointer to Global MAC structure 501 * @sa: Mac address of requesting peer 502 * @session: pointer to pe session entry 503 * @assoc_req: pointer to ASSOC/REASSOC Request frame 504 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 505 * 506 * Checks for non 11ac STA 507 * 508 * Return: true of no error, false otherwise 509 */ lim_chk_11ac_only(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)510 static bool lim_chk_11ac_only(struct mac_context *mac_ctx, tSirMacAddr sa, 511 struct pe_session *session, tpSirAssocReq assoc_req, 512 uint8_t sub_type) 513 { 514 tDot11fIEVHTCaps *vht_caps; 515 516 if (assoc_req->VHTCaps.present) 517 vht_caps = &assoc_req->VHTCaps; 518 else if (assoc_req->vendor_vht_ie.VHTCaps.present && 519 session->vendor_vht_sap) 520 vht_caps = &assoc_req->vendor_vht_ie.VHTCaps; 521 else 522 vht_caps = NULL; 523 524 if (LIM_IS_AP_ROLE(session) && 525 (session->dot11mode == MLME_DOT11_MODE_11AC_ONLY) && 526 ((!vht_caps) || ((vht_caps) && (!vht_caps->present)))) { 527 lim_send_assoc_rsp_mgmt_frame( 528 mac_ctx, STATUS_CAPS_UNSUPPORTED, 529 1, sa, sub_type, 0, session, false); 530 pe_err("SOFTAP was in 11AC only mode, reject"); 531 return false; 532 } 533 return true; 534 } 535 536 /** 537 * lim_chk_11ax_only() - checks for non 11ax STA 538 * @mac_ctx: pointer to Global MAC structure 539 * @sa: Mac address of requesting peer 540 * @session: pointer to pe session entry 541 * @assoc_req: pointer to ASSOC/REASSOC Request frame 542 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 543 * 544 * Checks for non 11ax STA 545 * 546 * Return: true of no error, false otherwise 547 */ 548 #ifdef WLAN_FEATURE_11AX lim_chk_11ax_only(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)549 static bool lim_chk_11ax_only(struct mac_context *mac_ctx, tSirMacAddr sa, 550 struct pe_session *session, tpSirAssocReq assoc_req, 551 uint8_t sub_type) 552 { 553 if (LIM_IS_AP_ROLE(session) && 554 (session->dot11mode == MLME_DOT11_MODE_11AX_ONLY) && 555 !assoc_req->he_cap.present) { 556 lim_send_assoc_rsp_mgmt_frame( 557 mac_ctx, STATUS_CAPS_UNSUPPORTED, 558 1, sa, sub_type, 0, session, false); 559 pe_err("SOFTAP was in 11AX only mode, reject"); 560 return false; 561 } 562 return true; 563 } 564 565 /** 566 * lim_check_11ax_basic_mcs() - checks for 11ax basic MCS rates 567 * @mac_ctx: pointer to Global MAC structure 568 * @sa: Mac address of requesting peer 569 * @session: pointer to pe session entry 570 * @assoc_req: pointer to ASSOC/REASSOC Request frame 571 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 572 * 573 * Checks for non 11ax STA 574 * 575 * Return: true of no error, false otherwise 576 */ lim_check_11ax_basic_mcs(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)577 static bool lim_check_11ax_basic_mcs(struct mac_context *mac_ctx, 578 tSirMacAddr sa, 579 struct pe_session *session, 580 tpSirAssocReq assoc_req, 581 uint8_t sub_type) 582 { 583 uint16_t basic_mcs, sta_mcs, rx_mcs, tx_mcs, final_mcs; 584 585 if (LIM_IS_AP_ROLE(session) && 586 assoc_req->he_cap.present) { 587 rx_mcs = assoc_req->he_cap.rx_he_mcs_map_lt_80; 588 tx_mcs = assoc_req->he_cap.tx_he_mcs_map_lt_80; 589 sta_mcs = HE_INTERSECT_MCS(rx_mcs, tx_mcs); 590 basic_mcs = 591 (uint16_t)mac_ctx->mlme_cfg->he_caps.he_ops_basic_mcs_nss; 592 final_mcs = HE_INTERSECT_MCS(sta_mcs, basic_mcs); 593 if (final_mcs != basic_mcs) { 594 lim_send_assoc_rsp_mgmt_frame( 595 mac_ctx, 596 STATUS_CAPS_UNSUPPORTED, 597 1, sa, sub_type, 0, session, false); 598 pe_err("STA did not support basic MCS required by SAP"); 599 return false; 600 } 601 } 602 return true; 603 } 604 605 #else lim_chk_11ax_only(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)606 static bool lim_chk_11ax_only(struct mac_context *mac_ctx, tSirMacAddr sa, 607 struct pe_session *session, tpSirAssocReq assoc_req, 608 uint8_t sub_type) 609 { 610 return true; 611 } 612 lim_check_11ax_basic_mcs(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)613 static bool lim_check_11ax_basic_mcs(struct mac_context *mac_ctx, 614 tSirMacAddr sa, 615 struct pe_session *session, 616 tpSirAssocReq assoc_req, 617 uint8_t sub_type) 618 { 619 return true; 620 } 621 #endif 622 623 /** 624 * lim_chk_11be_only() - checks for non 11be STA 625 * @mac_ctx: pointer to Global MAC structure 626 * @sa: Mac address of requesting peer 627 * @session: pointer to pe session entry 628 * @assoc_req: pointer to ASSOC/REASSOC Request frame 629 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 630 * 631 * Checks for non 11be STA 632 * 633 * Return: true if no error, false otherwise 634 */ 635 #ifdef WLAN_FEATURE_11BE lim_chk_11be_only(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)636 static bool lim_chk_11be_only(struct mac_context *mac_ctx, tSirMacAddr sa, 637 struct pe_session *session, 638 tpSirAssocReq assoc_req, uint8_t sub_type) 639 { 640 if (LIM_IS_AP_ROLE(session) && 641 (session->dot11mode == MLME_DOT11_MODE_11BE_ONLY) && 642 !assoc_req->eht_cap.present) { 643 lim_send_assoc_rsp_mgmt_frame( 644 mac_ctx, STATUS_CAPS_UNSUPPORTED, 645 1, sa, sub_type, 0, session, false); 646 pe_err("SOFTAP was in 11BE only mode, reject"); 647 return false; 648 } 649 return true; 650 } 651 #else lim_chk_11be_only(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)652 static bool lim_chk_11be_only(struct mac_context *mac_ctx, tSirMacAddr sa, 653 struct pe_session *session, 654 tpSirAssocReq assoc_req, uint8_t sub_type) 655 { 656 return true; 657 } 658 #endif 659 660 /** 661 * lim_process_for_spectrum_mgmt() - process assoc req for spectrum mgmt 662 * @mac_ctx: pointer to Global MAC structure 663 * @sa: Mac address of requesting peer 664 * @session: pointer to pe session entry 665 * @assoc_req: pointer to ASSOC/REASSOC Request frame 666 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 667 * @local_cap: local capabilities of SAP 668 * 669 * Checks for SSID match 670 * 671 * process assoc req for spectrum mgmt 672 */ 673 static void lim_process_for_spectrum_mgmt(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,tSirMacCapabilityInfo local_cap)674 lim_process_for_spectrum_mgmt(struct mac_context *mac_ctx, tSirMacAddr sa, 675 struct pe_session *session, tpSirAssocReq assoc_req, 676 uint8_t sub_type, tSirMacCapabilityInfo local_cap) 677 { 678 if (local_cap.spectrumMgt) { 679 QDF_STATUS status = QDF_STATUS_SUCCESS; 680 /* 681 * If station is 11h capable, then it SHOULD send all mandatory 682 * IEs in assoc request frame. Let us verify that 683 */ 684 if (assoc_req->capabilityInfo.spectrumMgt) { 685 if (!((assoc_req->powerCapabilityPresent) 686 && (assoc_req->supportedChannelsPresent))) { 687 /* 688 * One or more required information elements are 689 * missing, log the peers error 690 */ 691 if (!assoc_req->powerCapabilityPresent) { 692 pe_warn("LIM Info: Missing Power capability IE in %s Req from " 693 QDF_MAC_ADDR_FMT, 694 (LIM_ASSOC == sub_type) ? 695 "Assoc" : "ReAssoc", 696 QDF_MAC_ADDR_REF(sa)); 697 } 698 if (!assoc_req->supportedChannelsPresent) { 699 pe_warn("LIM Info: Missing Supported channel IE in %s Req from " 700 QDF_MAC_ADDR_FMT, 701 (LIM_ASSOC == sub_type) ? 702 "Assoc" : "ReAssoc", 703 QDF_MAC_ADDR_REF(sa)); 704 } 705 } else { 706 /* Assoc request has mandatory fields */ 707 status = 708 lim_is_dot11h_power_capabilities_in_range( 709 mac_ctx, assoc_req, session); 710 if (QDF_STATUS_SUCCESS != status) { 711 pe_warn("LIM Info: MinTxPower(STA) > MaxTxPower(AP) in %s Req from " 712 QDF_MAC_ADDR_FMT, 713 (LIM_ASSOC == sub_type) ? 714 "Assoc" : "ReAssoc", 715 QDF_MAC_ADDR_REF(sa)); 716 } 717 status = lim_is_dot11h_supported_channels_valid( 718 mac_ctx, assoc_req); 719 if (QDF_STATUS_SUCCESS != status) { 720 pe_warn("LIM Info: wrong supported channels (STA) in %s Req from " 721 QDF_MAC_ADDR_FMT, 722 (LIM_ASSOC == sub_type) ? 723 "Assoc" : "ReAssoc", 724 QDF_MAC_ADDR_REF(sa)); 725 } 726 /* IEs are valid, use them if needed */ 727 } 728 } /* if(assoc.capabilityInfo.spectrumMgt) */ 729 else { 730 /* 731 * As per the capabilities, the spectrum management is 732 * not enabled on the station. The AP may allow the 733 * associations to happen even if spectrum management 734 * is not allowed, if the transmit power of station is 735 * below the regulatory maximum 736 */ 737 738 /* 739 * TODO: presently, this is not handled. In the current 740 * implementation, the AP would allow the station to 741 * associate even if it doesn't support spectrum 742 * management. 743 */ 744 } 745 } /* end of spectrum management related processing */ 746 } 747 748 /** 749 * lim_chk_mcs() - checks for supported MCS 750 * @mac_ctx: pointer to Global MAC structure 751 * @sa: Mac address of requesting peer 752 * @session: pointer to pe session entry 753 * @assoc_req: pointer to ASSOC/REASSOC Request frame 754 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 755 * 756 * Checks for supported MCS 757 * 758 * Return: true of no error, false otherwise 759 */ lim_chk_mcs(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)760 static bool lim_chk_mcs(struct mac_context *mac_ctx, tSirMacAddr sa, 761 struct pe_session *session, tpSirAssocReq assoc_req, 762 uint8_t sub_type) 763 { 764 if ((assoc_req->HTCaps.present) && (lim_check_mcs_set(mac_ctx, 765 assoc_req->HTCaps.supportedMCSSet) == false)) { 766 pe_warn("rcvd %s req with unsupported MCS Rate Set from " 767 QDF_MAC_ADDR_FMT, 768 (LIM_ASSOC == sub_type) ? "Assoc" : "ReAssoc", 769 QDF_MAC_ADDR_REF(sa)); 770 /* 771 * Requesting STA does not support ALL BSS MCS basic Rate set 772 * rates. Spec does not define any status code for this 773 * scenario. 774 */ 775 lim_send_assoc_rsp_mgmt_frame( 776 mac_ctx, STATUS_ASSOC_DENIED_UNSPEC, 777 1, sa, sub_type, 0, session, false); 778 return false; 779 } 780 return true; 781 } 782 783 /** 784 * lim_chk_is_11b_sta_supported() - checks if STA is 11b 785 * @mac_ctx: pointer to Global MAC structure 786 * @sa: Mac address of requesting peer 787 * @session: pointer to pe session entry 788 * @assoc_req: pointer to ASSOC/REASSOC Request frame 789 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 790 * @phy_mode: phy mode 791 * 792 * Checks if STA is 11b 793 * 794 * Return: true of no error, false otherwise 795 */ lim_chk_is_11b_sta_supported(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,uint32_t phy_mode)796 static bool lim_chk_is_11b_sta_supported(struct mac_context *mac_ctx, 797 tSirMacAddr sa, 798 struct pe_session *session, 799 tpSirAssocReq assoc_req, 800 uint8_t sub_type, uint32_t phy_mode) 801 { 802 uint32_t cfg_11g_only; 803 804 if (phy_mode == WNI_CFG_PHY_MODE_11G) { 805 cfg_11g_only = mac_ctx->mlme_cfg->sap_cfg.sap_11g_policy; 806 if (!assoc_req->extendedRatesPresent && cfg_11g_only) { 807 /* 808 * Received Re/Association Request from 11b STA when 11g 809 * only policy option is set. Reject with unspecified 810 * status code. 811 */ 812 lim_send_assoc_rsp_mgmt_frame( 813 mac_ctx, 814 STATUS_ASSOC_DENIED_RATES, 815 1, sa, sub_type, 0, session, false); 816 817 pe_warn("Rejecting Re/Assoc req from 11b STA: "QDF_MAC_ADDR_FMT, 818 QDF_MAC_ADDR_REF(sa)); 819 820 return false; 821 } 822 } 823 return true; 824 } 825 826 /** 827 * lim_print_ht_cap() - prints HT caps 828 * @mac_ctx: pointer to Global MAC structure 829 * @session: pointer to pe session entry 830 * @assoc_req: pointer to ASSOC/REASSOC Request frame 831 * 832 * Prints HT caps 833 * 834 * Return: void 835 */ lim_print_ht_cap(struct mac_context * mac_ctx,struct pe_session * session,tpSirAssocReq assoc_req)836 static void lim_print_ht_cap(struct mac_context *mac_ctx, struct pe_session *session, 837 tpSirAssocReq assoc_req) 838 { 839 if (!session->htCapability) 840 return; 841 842 if (assoc_req->HTCaps.present) { 843 /* The station *does* support 802.11n HT capability... */ 844 pe_debug("AdvCodingCap:%d ChaWidthSet:%d PowerSave:%d greenField:%d shortGI20:%d shortGI40:%d txSTBC:%d rxSTBC:%d delayBA:%d maxAMSDUsize:%d DSSS/CCK:%d PSMP:%d stbcCntl:%d lsigTXProt:%d", 845 assoc_req->HTCaps.advCodingCap, 846 assoc_req->HTCaps.supportedChannelWidthSet, 847 assoc_req->HTCaps.mimoPowerSave, 848 assoc_req->HTCaps.greenField, 849 assoc_req->HTCaps.shortGI20MHz, 850 assoc_req->HTCaps.shortGI40MHz, 851 assoc_req->HTCaps.txSTBC, 852 assoc_req->HTCaps.rxSTBC, 853 assoc_req->HTCaps.delayedBA, 854 assoc_req->HTCaps.maximalAMSDUsize, 855 assoc_req->HTCaps.dsssCckMode40MHz, 856 assoc_req->HTCaps.psmp, 857 assoc_req->HTCaps.stbcControlFrame, 858 assoc_req->HTCaps.lsigTXOPProtection); 859 /* 860 * Make sure the STA's caps are compatible with our own: 861 * 11.15.2 Support of DSSS/CCK in 40 MHz the AP shall refuse 862 * association requests from an HT STA that has the DSSS/CCK 863 * Mode in 40 MHz subfield set to 1; 864 */ 865 } 866 } 867 868 static enum wlan_status_code lim_check_crypto_param(tpSirAssocReq assoc_req,struct wlan_crypto_params * peer_crypto_params)869 lim_check_crypto_param(tpSirAssocReq assoc_req, 870 struct wlan_crypto_params *peer_crypto_params) 871 { 872 /* TKIP/WEP is not allowed in HT/VHT mode*/ 873 if (assoc_req->HTCaps.present) { 874 if ((peer_crypto_params->ucastcipherset & 875 (1 << WLAN_CRYPTO_CIPHER_TKIP)) || 876 (peer_crypto_params->ucastcipherset & 877 (1 << WLAN_CRYPTO_CIPHER_WEP))) { 878 pe_info("TKIP/WEP cipher with HT supported client, reject assoc"); 879 return STATUS_INVALID_IE; 880 } 881 } 882 return STATUS_SUCCESS; 883 } 884 885 static lim_check_rsn_ie(struct pe_session * session,struct mac_context * mac_ctx,tpSirAssocReq assoc_req,bool * pmf_connection)886 enum wlan_status_code lim_check_rsn_ie(struct pe_session *session, 887 struct mac_context *mac_ctx, 888 tpSirAssocReq assoc_req, 889 bool *pmf_connection) 890 { 891 struct wlan_objmgr_vdev *vdev; 892 tSirMacRsnInfo *rsn_ie; 893 struct wlan_crypto_params peer_crypto_params; 894 895 rsn_ie = qdf_mem_malloc(sizeof(*rsn_ie)); 896 if (!rsn_ie) { 897 pe_err("malloc failed for rsn_ie"); 898 return STATUS_UNSPECIFIED_FAILURE; 899 } 900 901 rsn_ie->info[0] = WLAN_ELEMID_RSN; 902 rsn_ie->info[1] = assoc_req->rsn.length; 903 904 rsn_ie->length = assoc_req->rsn.length + 2; 905 qdf_mem_copy(&rsn_ie->info[2], assoc_req->rsn.info, 906 assoc_req->rsn.length); 907 if (wlan_crypto_check_rsn_match(mac_ctx->psoc, session->smeSessionId, 908 &rsn_ie->info[0], rsn_ie->length, 909 &peer_crypto_params)) { 910 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, 911 session->smeSessionId, 912 WLAN_LEGACY_MAC_ID); 913 if (!vdev) { 914 pe_err("vdev is NULL"); 915 qdf_mem_free(rsn_ie); 916 return STATUS_UNSPECIFIED_FAILURE; 917 } 918 if ((peer_crypto_params.rsn_caps & 919 WLAN_CRYPTO_RSN_CAP_MFP_ENABLED) && 920 wlan_crypto_vdev_is_pmf_enabled(vdev)) 921 *pmf_connection = true; 922 923 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); 924 qdf_mem_free(rsn_ie); 925 return lim_check_crypto_param(assoc_req, &peer_crypto_params); 926 927 } else { 928 qdf_mem_free(rsn_ie); 929 return STATUS_INVALID_IE; 930 } 931 932 qdf_mem_free(rsn_ie); 933 return STATUS_SUCCESS; 934 } 935 lim_check_wpa_ie(struct pe_session * session,struct mac_context * mac_ctx,tpSirAssocReq assoc_req,tDot11fIEWPA * wpa)936 static enum wlan_status_code lim_check_wpa_ie(struct pe_session *session, 937 struct mac_context *mac_ctx, 938 tpSirAssocReq assoc_req, 939 tDot11fIEWPA *wpa) 940 { 941 uint8_t *buffer; 942 uint32_t dot11f_status, written = 0, nbuffer = WLAN_MAX_IE_LEN; 943 tSirMacRsnInfo *wpa_ie; 944 struct wlan_crypto_params peer_crypto_params; 945 946 buffer = qdf_mem_malloc(WLAN_MAX_IE_LEN); 947 if (!buffer) { 948 pe_err("malloc failed for ie buffer"); 949 return STATUS_INVALID_IE; 950 } 951 952 dot11f_status = dot11f_pack_ie_wpa(mac_ctx, wpa, buffer, 953 nbuffer, &written); 954 if (DOT11F_FAILED(dot11f_status)) { 955 pe_err("Failed to re-pack the RSN IE (0x%0x8)", dot11f_status); 956 qdf_mem_free(buffer); 957 return STATUS_INVALID_IE; 958 } 959 960 wpa_ie = qdf_mem_malloc(sizeof(*wpa_ie)); 961 if (!wpa_ie) { 962 pe_err("malloc failed for wpa ie"); 963 qdf_mem_free(buffer); 964 return STATUS_INVALID_IE; 965 } 966 967 wpa_ie->length = (uint8_t)written; 968 qdf_mem_copy(&wpa_ie->info[0], buffer, wpa_ie->length); 969 qdf_mem_free(buffer); 970 971 if (wlan_crypto_check_wpa_match(mac_ctx->psoc, session->smeSessionId, 972 &wpa_ie->info[0], wpa_ie->length, 973 &peer_crypto_params)) { 974 qdf_mem_free(wpa_ie); 975 return lim_check_crypto_param(assoc_req, &peer_crypto_params); 976 } 977 978 qdf_mem_free(wpa_ie); 979 return STATUS_INVALID_IE; 980 } 981 982 /** 983 * lim_check_sae_pmf_cap() - check pmf capability for SAE STA 984 * @session: pointer to pe session entry 985 * @rsn: pointer to RSN 986 * @akm_type: AKM type 987 * 988 * This function checks if SAE STA is pmf capable when SAE SAP is pmf 989 * capable. Reject with eSIR_MAC_ROBUST_MGMT_FRAMES_POLICY_VIOLATION 990 * if SAE STA is pmf disable. 991 * 992 * Return: wlan_status_code 993 */ 994 #if defined(WLAN_FEATURE_SAE) lim_check_sae_pmf_cap(struct pe_session * session,tDot11fIERSN * rsn,enum ani_akm_type akm_type)995 static enum wlan_status_code lim_check_sae_pmf_cap(struct pe_session *session, 996 tDot11fIERSN *rsn, 997 enum ani_akm_type akm_type) 998 { 999 enum wlan_status_code status = STATUS_SUCCESS; 1000 1001 if (session->limRmfEnabled && 1002 (rsn->RSN_Cap[0] & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED) == 0 && 1003 akm_type == ANI_AKM_TYPE_SAE) 1004 status = STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; 1005 1006 return status; 1007 } 1008 #else lim_check_sae_pmf_cap(struct pe_session * session,tDot11fIERSN * rsn,enum ani_akm_type akm_type)1009 static enum wlan_status_code lim_check_sae_pmf_cap(struct pe_session *session, 1010 tDot11fIERSN *rsn, 1011 enum ani_akm_type akm_type) 1012 { 1013 return STATUS_SUCCESS; 1014 } 1015 #endif 1016 1017 /** 1018 * lim_check_wpa_rsn_ie() - wpa and rsn ie related checks 1019 * @session: pointer to pe session entry 1020 * @mac_ctx: pointer to Global MAC structure 1021 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 1022 * @sa: Mac address of requesting peer 1023 * @assoc_req: pointer to ASSOC/REASSOC Request frame 1024 * @pmf_connection: flag indicating pmf connection 1025 * @akm_type: AKM type 1026 * 1027 * This function checks if wpa/rsn IE is present and validates 1028 * ie version, length and mismatch. 1029 * 1030 * Return: true if no error, false otherwise 1031 */ lim_check_wpa_rsn_ie(struct pe_session * session,struct mac_context * mac_ctx,uint8_t sub_type,tSirMacAddr sa,tpSirAssocReq assoc_req,bool * pmf_connection,enum ani_akm_type * akm_type)1032 static bool lim_check_wpa_rsn_ie(struct pe_session *session, 1033 struct mac_context *mac_ctx, 1034 uint8_t sub_type, tSirMacAddr sa, 1035 tpSirAssocReq assoc_req, bool *pmf_connection, 1036 enum ani_akm_type *akm_type) 1037 { 1038 uint32_t ret; 1039 tDot11fIEWPA dot11f_ie_wpa = {0}; 1040 tDot11fIERSN dot11f_ie_rsn = {0}; 1041 enum wlan_status_code status = STATUS_SUCCESS; 1042 1043 /* 1044 * Clear the buffers so that frame parser knows that there isn't a 1045 * previously decoded IE in these buffers 1046 */ 1047 qdf_mem_zero((uint8_t *) &dot11f_ie_rsn, sizeof(dot11f_ie_rsn)); 1048 qdf_mem_zero((uint8_t *) &dot11f_ie_wpa, sizeof(dot11f_ie_wpa)); 1049 pe_debug("RSN enabled auth, Re/Assoc req from STA: " 1050 QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(sa)); 1051 1052 if (assoc_req->rsnPresent) { 1053 if (!(assoc_req->rsn.length)) { 1054 pe_warn("Re/Assoc rejected from: " 1055 QDF_MAC_ADDR_FMT, 1056 QDF_MAC_ADDR_REF(sa)); 1057 /* 1058 * rcvd Assoc req frame with RSN IE but 1059 * length is zero 1060 */ 1061 lim_send_assoc_rsp_mgmt_frame( 1062 mac_ctx, STATUS_INVALID_IE, 1, 1063 sa, sub_type, 0, session, false); 1064 return false; 1065 } 1066 1067 /* Unpack the RSN IE */ 1068 ret = dot11f_unpack_ie_rsn(mac_ctx, 1069 &assoc_req->rsn.info[0], 1070 assoc_req->rsn.length, 1071 &dot11f_ie_rsn, false); 1072 if (!DOT11F_SUCCEEDED(ret)) { 1073 pe_err("Invalid RSN IE"); 1074 lim_send_assoc_rsp_mgmt_frame( 1075 mac_ctx, STATUS_INVALID_IE, 1, 1076 sa, sub_type, 0, session, false); 1077 return false; 1078 } 1079 1080 /* Check if the RSN version is supported */ 1081 if (SIR_MAC_OUI_VERSION_1 == dot11f_ie_rsn.version) { 1082 /* check the groupwise and pairwise cipher suites */ 1083 status = lim_check_rsn_ie(session, mac_ctx, assoc_req, 1084 pmf_connection); 1085 if (status != STATUS_SUCCESS) { 1086 pe_warn("Re/Assoc rejected from: " 1087 QDF_MAC_ADDR_FMT, 1088 QDF_MAC_ADDR_REF(sa)); 1089 1090 lim_send_assoc_rsp_mgmt_frame( 1091 mac_ctx, status, 1, sa, sub_type, 1092 0, session, false); 1093 return false; 1094 } 1095 } else { 1096 pe_warn("Re/Assoc rejected from: " QDF_MAC_ADDR_FMT, 1097 QDF_MAC_ADDR_REF(sa)); 1098 /* 1099 * rcvd Assoc req frame with RSN IE but 1100 * IE version is wrong 1101 */ 1102 lim_send_assoc_rsp_mgmt_frame( 1103 mac_ctx, 1104 STATUS_UNSUPPORTED_RSN_IE_VERSION, 1105 1, sa, sub_type, 0, session, false); 1106 return false; 1107 } 1108 *akm_type = lim_translate_rsn_oui_to_akm_type( 1109 dot11f_ie_rsn.akm_suite[0]); 1110 1111 status = lim_check_sae_pmf_cap(session, &dot11f_ie_rsn, 1112 *akm_type); 1113 if (status != STATUS_SUCCESS) { 1114 /* Reject pmf disable SAE STA */ 1115 pe_warn("Re/Assoc rejected from: " QDF_MAC_ADDR_FMT, 1116 QDF_MAC_ADDR_REF(sa)); 1117 lim_send_assoc_rsp_mgmt_frame(mac_ctx, status, 1118 1, sa, sub_type, 1119 0, session, false); 1120 return false; 1121 } 1122 1123 } else if (assoc_req->wpaPresent) { 1124 if (!(assoc_req->wpa.length)) { 1125 pe_warn("Re/Assoc rejected from: " 1126 QDF_MAC_ADDR_FMT, 1127 QDF_MAC_ADDR_REF(sa)); 1128 1129 /* rcvd Assoc req frame with invalid WPA IE length */ 1130 lim_send_assoc_rsp_mgmt_frame( 1131 mac_ctx, STATUS_INVALID_IE, 1, 1132 sa, sub_type, 0, session, false); 1133 return false; 1134 } 1135 /* Unpack the WPA IE */ 1136 ret = dot11f_unpack_ie_wpa(mac_ctx, 1137 &assoc_req->wpa.info[4], 1138 (assoc_req->wpa.length - 4), 1139 &dot11f_ie_wpa, false); 1140 if (!DOT11F_SUCCEEDED(ret)) { 1141 pe_err("Invalid WPA IE"); 1142 lim_send_assoc_rsp_mgmt_frame( 1143 mac_ctx, STATUS_INVALID_IE, 1, 1144 sa, sub_type, 0, session, false); 1145 return false; 1146 } 1147 1148 /* check the groupwise and pairwise cipher suites*/ 1149 status = lim_check_wpa_ie(session, mac_ctx, assoc_req, 1150 &dot11f_ie_wpa); 1151 if (status != STATUS_SUCCESS) { 1152 pe_warn("Re/Assoc rejected from: " 1153 QDF_MAC_ADDR_FMT, 1154 QDF_MAC_ADDR_REF(sa)); 1155 /* 1156 * rcvd Assoc req frame with WPA IE 1157 * but there is mismatch 1158 */ 1159 lim_send_assoc_rsp_mgmt_frame( 1160 mac_ctx, status, 1, 1161 sa, sub_type, 0, session, false); 1162 return false; 1163 } 1164 *akm_type = lim_translate_rsn_oui_to_akm_type( 1165 dot11f_ie_wpa.auth_suites[0]); 1166 } else { 1167 if ((session->gStartBssRSNIe.present || 1168 session->gStartBssWPAIe.present) && 1169 session->opmode == QDF_SAP_MODE) { 1170 pe_warn("STA does not support RSN and WPA!"); 1171 lim_send_assoc_rsp_mgmt_frame( 1172 mac_ctx, STATUS_NOT_SUPPORTED_AUTH_ALG, 1, 1173 sa, sub_type, 0, session, false); 1174 return false; 1175 } 1176 } 1177 1178 return true; 1179 } 1180 1181 /** 1182 * lim_chk_n_process_wpa_rsn_ie() - wpa ie related checks 1183 * @mac_ctx: pointer to Global MAC structure 1184 * @sa: Mac address of requesting peer 1185 * @session: pointer to pe session entry 1186 * @assoc_req: pointer to ASSOC/REASSOC Request frame 1187 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 1188 * @pmf_connection: flag indicating pmf connection 1189 * @akm_type: AKM type 1190 * 1191 * wpa ie related checks 1192 * 1193 * Return: true if no error, false otherwise 1194 */ lim_chk_n_process_wpa_rsn_ie(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,bool * pmf_connection,enum ani_akm_type * akm_type)1195 static bool lim_chk_n_process_wpa_rsn_ie(struct mac_context *mac_ctx, 1196 tSirMacAddr sa, 1197 struct pe_session *session, 1198 tpSirAssocReq assoc_req, 1199 uint8_t sub_type, 1200 bool *pmf_connection, 1201 enum ani_akm_type *akm_type) 1202 { 1203 const uint8_t *wps_ie = NULL; 1204 1205 /* if additional IE is present, check if it has WscIE */ 1206 if (assoc_req->addIEPresent && assoc_req->addIE.length) 1207 wps_ie = limGetWscIEPtr(mac_ctx, assoc_req->addIE.addIEdata, 1208 assoc_req->addIE.length); 1209 else 1210 pe_debug("Assoc req addIEPresent: %d addIE length: %d", 1211 assoc_req->addIEPresent, assoc_req->addIE.length); 1212 1213 /* when wps_ie is present, RSN/WPA IE is ignored */ 1214 if (!wps_ie) { 1215 /* check whether RSN IE is present */ 1216 if (LIM_IS_AP_ROLE(session) && 1217 session->pLimStartBssReq->privacy && 1218 session->pLimStartBssReq->rsnIE.length) 1219 return lim_check_wpa_rsn_ie(session, mac_ctx, sub_type, 1220 sa, assoc_req, pmf_connection, 1221 akm_type); 1222 } else { 1223 pe_debug("Assoc req WSE IE is present"); 1224 } 1225 return true; 1226 } 1227 1228 /** 1229 * lim_process_assoc_req_no_sta_ctx() - process assoc req for no sta ctx present 1230 * @mac_ctx: pointer to Global MAC structure 1231 * @sa: Mac address of requesting peer 1232 * @session: pointer to pe session entry 1233 * @assoc_req: pointer to ASSOC/REASSOC Request frame 1234 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 1235 * @sta_pre_auth_ctx: sta pre auth context 1236 * @sta_ds: station dph entry 1237 * @auth_type: indicates security type 1238 * @partner_peer_idx: partner peer idx 1239 * 1240 * Process assoc req for no sta ctx present 1241 * 1242 * Return: true of no error, false otherwise 1243 */ lim_process_assoc_req_no_sta_ctx(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,struct tLimPreAuthNode * sta_pre_auth_ctx,tpDphHashNode sta_ds,tAniAuthType * auth_type,uint16_t partner_peer_idx)1244 static bool lim_process_assoc_req_no_sta_ctx(struct mac_context *mac_ctx, 1245 tSirMacAddr sa, struct pe_session *session, 1246 tpSirAssocReq assoc_req, uint8_t sub_type, 1247 struct tLimPreAuthNode *sta_pre_auth_ctx, 1248 tpDphHashNode sta_ds, tAniAuthType *auth_type, 1249 uint16_t partner_peer_idx) 1250 { 1251 /* Requesting STA is not currently associated */ 1252 if (pe_get_current_stas_count(mac_ctx) == 1253 mac_ctx->mlme_cfg->sap_cfg.assoc_sta_limit) { 1254 /* 1255 * Maximum number of STAs that AP can handle reached. 1256 * Send Association response to peer MAC entity 1257 */ 1258 pe_info_rl("Max Sta count reached : %d", 1259 mac_ctx->lim.maxStation); 1260 lim_reject_association(mac_ctx, sa, sub_type, false, 1261 (tAniAuthType)0, 0, false, 1262 STATUS_UNSPECIFIED_FAILURE, 1263 session); 1264 return false; 1265 } 1266 /* Check if STA is pre-authenticated. */ 1267 if ((!sta_pre_auth_ctx && !partner_peer_idx) || 1268 (sta_pre_auth_ctx && sta_pre_auth_ctx->mlmState != 1269 eLIM_MLM_AUTHENTICATED_STATE)) { 1270 /* 1271 * STA is not pre-authenticated yet requesting Re/Association 1272 * before Authentication. OR STA is in the process of getting 1273 * authenticated and sent Re/Association request. Send 1274 * Deauthentication frame with 'prior authentication required' 1275 * reason code. 1276 */ 1277 lim_send_deauth_mgmt_frame(mac_ctx, 1278 REASON_STA_NOT_AUTHENTICATED, 1279 sa, session, false); 1280 1281 pe_warn("rcvd %s req, sessionid: %d, without pre-auth ctx" 1282 QDF_MAC_ADDR_FMT, 1283 (LIM_ASSOC == sub_type) ? "Assoc" : "ReAssoc", 1284 session->peSessionId, QDF_MAC_ADDR_REF(sa)); 1285 return false; 1286 } 1287 if (partner_peer_idx) { 1288 if (!lim_mlo_partner_auth_type(session, partner_peer_idx, 1289 auth_type)) { 1290 pe_err("can't get partner auth type"); 1291 return false; 1292 } 1293 } else { 1294 /* Delete 'pre-auth' context of STA */ 1295 *auth_type = sta_pre_auth_ctx->authType; 1296 if (sta_pre_auth_ctx->authType == eSIR_AUTH_TYPE_SAE) 1297 assoc_req->is_sae_authenticated = true; 1298 lim_delete_pre_auth_node(mac_ctx, sa); 1299 } 1300 /* All is well. Assign AID (after else part) */ 1301 return true; 1302 } 1303 1304 static inline void lim_delete_pmf_query_timer(tpDphHashNode sta_ds)1305 lim_delete_pmf_query_timer(tpDphHashNode sta_ds) 1306 { 1307 if (!sta_ds->rmfEnabled) 1308 return; 1309 1310 if (tx_timer_running(&sta_ds->pmfSaQueryTimer)) 1311 tx_timer_deactivate(&sta_ds->pmfSaQueryTimer); 1312 tx_timer_delete(&sta_ds->pmfSaQueryTimer); 1313 } 1314 1315 /** 1316 * lim_process_assoc_req_sta_ctx() - process assoc req for sta context present 1317 * @mac_ctx: pointer to Global MAC structure 1318 * @sa: Mac address of requesting peer 1319 * @session: pointer to pe session entry 1320 * @assoc_req: pointer to ASSOC/REASSOC Request frame 1321 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 1322 * @sta_pre_auth_ctx: sta pre auth context 1323 * @sta_ds: station dph entry 1324 * @peer_idx: peer index 1325 * @auth_type: indicates security type 1326 * @update_ctx: indicates if STA context already exist 1327 * 1328 * Process assoc req for sta context present 1329 * 1330 * Return: true of no error, false otherwise 1331 */ lim_process_assoc_req_sta_ctx(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,struct tLimPreAuthNode * sta_pre_auth_ctx,tpDphHashNode sta_ds,uint16_t peer_idx,tAniAuthType * auth_type,uint8_t * update_ctx)1332 static bool lim_process_assoc_req_sta_ctx(struct mac_context *mac_ctx, 1333 tSirMacAddr sa, struct pe_session *session, 1334 tpSirAssocReq assoc_req, uint8_t sub_type, 1335 struct tLimPreAuthNode *sta_pre_auth_ctx, 1336 tpDphHashNode sta_ds, uint16_t peer_idx, 1337 tAniAuthType *auth_type, uint8_t *update_ctx) 1338 { 1339 /* Drop if STA deletion is in progress or not in established state */ 1340 if (sta_ds->sta_deletion_in_progress || 1341 (sta_ds->mlmStaContext.mlmState != 1342 eLIM_MLM_LINK_ESTABLISHED_STATE)) { 1343 pe_debug("%s: peer:"QDF_MAC_ADDR_FMT" in mlmState %d (%s) and sta del %d", 1344 (sub_type == LIM_ASSOC) ? "Assoc" : "ReAssoc", 1345 QDF_MAC_ADDR_REF(sta_ds->staAddr), 1346 sta_ds->mlmStaContext.mlmState, 1347 lim_mlm_state_str(sta_ds->mlmStaContext.mlmState), 1348 sta_ds->sta_deletion_in_progress); 1349 return false; 1350 } 1351 1352 /* STA sent assoc req frame while already in 'associated' state */ 1353 1354 pe_debug("Re/Assoc request from station that is already associated"); 1355 pe_debug("PMF enabled: %d, SA Query state: %d", 1356 sta_ds->rmfEnabled, sta_ds->pmfSaQueryState); 1357 if (sta_ds->rmfEnabled) { 1358 switch (sta_ds->pmfSaQueryState) { 1359 /* 1360 * start SA Query procedure, respond to Association Request with 1361 * try again later 1362 */ 1363 case DPH_SA_QUERY_NOT_IN_PROGRESS: 1364 /* 1365 * We should reset the retry counter before we start 1366 * the SA query procedure, otherwise in next set of SA 1367 * query procedure we will end up using the stale value. 1368 */ 1369 sta_ds->pmfSaQueryRetryCount = 0; 1370 lim_send_assoc_rsp_mgmt_frame( 1371 mac_ctx, STATUS_ASSOC_REJECTED_TEMPORARILY, 1, 1372 sa, sub_type, sta_ds, session, false); 1373 lim_send_sa_query_request_frame(mac_ctx, 1374 (uint8_t *) &(sta_ds->pmfSaQueryCurrentTransId), 1375 sa, session); 1376 sta_ds->pmfSaQueryStartTransId = 1377 sta_ds->pmfSaQueryCurrentTransId; 1378 sta_ds->pmfSaQueryCurrentTransId++; 1379 1380 /* start timer for SA Query retry */ 1381 if (tx_timer_activate(&sta_ds->pmfSaQueryTimer) 1382 != TX_SUCCESS) { 1383 pe_err("PMF SA Query timer start failed!"); 1384 return false; 1385 } 1386 sta_ds->pmfSaQueryState = DPH_SA_QUERY_IN_PROGRESS; 1387 return false; 1388 /* 1389 * SA Query procedure still going, respond to Association 1390 * Request with try again later 1391 */ 1392 case DPH_SA_QUERY_IN_PROGRESS: 1393 lim_send_assoc_rsp_mgmt_frame( 1394 mac_ctx, STATUS_ASSOC_REJECTED_TEMPORARILY, 1, 1395 sa, sub_type, 0, session, false); 1396 return false; 1397 1398 /* 1399 * SA Query procedure timed out, accept Association 1400 * Request normally 1401 */ 1402 case DPH_SA_QUERY_TIMED_OUT: 1403 sta_ds->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS; 1404 break; 1405 } 1406 } 1407 1408 /* no change in the capability so drop the frame */ 1409 if ((sub_type == LIM_ASSOC) && 1410 (!qdf_mem_cmp(&sta_ds->mlmStaContext.capabilityInfo, 1411 &assoc_req->capabilityInfo, 1412 sizeof(tSirMacCapabilityInfo)))) { 1413 pe_err("Received Assoc req in state: %X STAid: %d", 1414 sta_ds->mlmStaContext.mlmState, peer_idx); 1415 return false; 1416 } 1417 1418 /* 1419 * STA sent Re/association Request frame while already in 1420 * 'associated' state. Update STA capabilities and send 1421 * Association response frame with same AID 1422 */ 1423 pe_debug("Rcvd Assoc req from STA already connected"); 1424 sta_ds->mlmStaContext.capabilityInfo = 1425 assoc_req->capabilityInfo; 1426 if (sta_pre_auth_ctx && (sta_pre_auth_ctx->mlmState == 1427 eLIM_MLM_AUTHENTICATED_STATE)) { 1428 /* STA has triggered pre-auth again */ 1429 *auth_type = sta_pre_auth_ctx->authType; 1430 lim_delete_pre_auth_node(mac_ctx, sa); 1431 } else { 1432 *auth_type = sta_ds->mlmStaContext.authType; 1433 } 1434 1435 *update_ctx = true; 1436 /* Free pmf query timer before resetting the sta_ds */ 1437 lim_delete_pmf_query_timer(sta_ds); 1438 if (dph_init_sta_state(mac_ctx, sa, peer_idx, 1439 &session->dph.dphHashTable) == NULL) { 1440 pe_err("could not Init STAid: %d", peer_idx); 1441 return false; 1442 } 1443 1444 return true; 1445 } 1446 1447 /** 1448 * lim_chk_wmm() - wmm related checks 1449 * @mac_ctx: pointer to Global MAC structure 1450 * @sa: Mac address of requesting peer 1451 * @session: pointer to pe session entry 1452 * @assoc_req: pointer to ASSOC/REASSOC Request frame 1453 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 1454 * @qos_mode: qos mode 1455 * 1456 * wmm related checks 1457 * 1458 * Return: true of no error, false otherwise 1459 */ lim_chk_wmm(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,tHalBitVal qos_mode)1460 static bool lim_chk_wmm(struct mac_context *mac_ctx, tSirMacAddr sa, 1461 struct pe_session *session, tpSirAssocReq assoc_req, 1462 uint8_t sub_type, tHalBitVal qos_mode) 1463 { 1464 tHalBitVal wme_mode; 1465 1466 limGetWmeMode(session, &wme_mode); 1467 if ((qos_mode == eHAL_SET) || (wme_mode == eHAL_SET)) { 1468 /* 1469 * for a qsta, check if the requested Traffic spec is admissible 1470 * for a non-qsta check if the sta can be admitted 1471 */ 1472 if (assoc_req->addtsPresent) { 1473 uint8_t tspecIdx = 0; 1474 1475 if (lim_admit_control_add_ts( 1476 mac_ctx, sa, 1477 &(assoc_req->addtsReq), 1478 &(assoc_req->qosCapability), 1479 0, false, NULL, &tspecIdx, session) != 1480 QDF_STATUS_SUCCESS) { 1481 pe_warn("AdmitControl: TSPEC rejected"); 1482 lim_send_assoc_rsp_mgmt_frame( 1483 mac_ctx, REASON_NO_BANDWIDTH, 1484 1, sa, sub_type, 0, session, 1485 false); 1486 return false; 1487 } 1488 } else if (lim_admit_control_add_sta(mac_ctx, sa, false) 1489 != QDF_STATUS_SUCCESS) { 1490 pe_warn("AdmitControl: Sta rejected"); 1491 lim_send_assoc_rsp_mgmt_frame( 1492 mac_ctx, REASON_NO_BANDWIDTH, 1, 1493 sa, sub_type, 0, session, false); 1494 return false; 1495 } 1496 /* else all ok */ 1497 pe_debug("AdmitControl: Sta OK!"); 1498 } 1499 return true; 1500 } 1501 lim_update_sta_ds_op_classes(tpSirAssocReq assoc_req,tpDphHashNode sta_ds)1502 static void lim_update_sta_ds_op_classes(tpSirAssocReq assoc_req, 1503 tpDphHashNode sta_ds) 1504 { 1505 qdf_mem_copy(&sta_ds->supp_operating_classes, 1506 &assoc_req->supp_operating_classes, 1507 sizeof(tDot11fIESuppOperatingClasses)); 1508 } 1509 lim_is_ocv_enable_in_assoc_req(struct mac_context * mac_ctx,struct sSirAssocReq * assoc_req)1510 static bool lim_is_ocv_enable_in_assoc_req(struct mac_context *mac_ctx, 1511 struct sSirAssocReq *assoc_req) 1512 { 1513 uint32_t ret; 1514 tDot11fIERSN dot11f_ie_rsn = {0}; 1515 1516 if ((assoc_req->rsnPresent) && !(assoc_req->rsn.length)) 1517 return false; 1518 1519 /* Unpack the RSN IE */ 1520 ret = dot11f_unpack_ie_rsn(mac_ctx, &assoc_req->rsn.info[0], 1521 assoc_req->rsn.length, &dot11f_ie_rsn, 1522 false); 1523 if (!DOT11F_SUCCEEDED(ret)) 1524 return false; 1525 1526 if (*(uint16_t *)&dot11f_ie_rsn.RSN_Cap & 1527 WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED) 1528 return true; 1529 1530 return false; 1531 } 1532 1533 /** 1534 * lim_update_sta_ds() - updates ds dph entry 1535 * @mac_ctx: pointer to Global MAC structure 1536 * @sa: Mac address of requesting peer 1537 * @session: pointer to pe session entry 1538 * @assoc_req: pointer to ASSOC/REASSOC Request frame pointer 1539 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 1540 * @sta_ds: station dph entry 1541 * @auth_type: indicates security type 1542 * @akm_type: indicates security type in akm 1543 * @assoc_req_copied: boolean to indicate if assoc req was copied to tmp above 1544 * @peer_idx: peer index 1545 * @qos_mode: qos mode 1546 * @pmf_connection: flag indicating pmf connection 1547 * @force_1x1: Flag to check if the HT capable STA needs to be downgraded to 1x1 1548 * nss. 1549 * 1550 * Updates ds dph entry 1551 * 1552 * Return: true of no error, false otherwise 1553 */ lim_update_sta_ds(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,tpDphHashNode sta_ds,tAniAuthType auth_type,enum ani_akm_type akm_type,bool * assoc_req_copied,uint16_t peer_idx,tHalBitVal qos_mode,bool pmf_connection,bool force_1x1)1554 static bool lim_update_sta_ds(struct mac_context *mac_ctx, tSirMacAddr sa, 1555 struct pe_session *session, 1556 tpSirAssocReq assoc_req, 1557 uint8_t sub_type, tpDphHashNode sta_ds, 1558 tAniAuthType auth_type, 1559 enum ani_akm_type akm_type, 1560 bool *assoc_req_copied, uint16_t peer_idx, 1561 tHalBitVal qos_mode, bool pmf_connection, 1562 bool force_1x1) 1563 { 1564 tHalBitVal wme_mode, wsm_mode; 1565 uint8_t *ht_cap_ie = NULL; 1566 tPmfSaQueryTimerId timer_id; 1567 uint16_t retry_interval; 1568 tDot11fIEVHTCaps *vht_caps; 1569 tpSirAssocReq tmp_assoc_req; 1570 1571 if (assoc_req->VHTCaps.present) 1572 vht_caps = &assoc_req->VHTCaps; 1573 else if (assoc_req->vendor_vht_ie.VHTCaps.present && 1574 session->vendor_vht_sap) 1575 vht_caps = &assoc_req->vendor_vht_ie.VHTCaps; 1576 else 1577 vht_caps = NULL; 1578 1579 /* 1580 * check here if the parsedAssocReq already pointing to the assoc_req 1581 * and free it before assigning this new assoc_req 1582 */ 1583 if (session->parsedAssocReq) { 1584 tmp_assoc_req = session->parsedAssocReq[sta_ds->assocId]; 1585 if (tmp_assoc_req) { 1586 lim_free_assoc_req_frm_buf(tmp_assoc_req); 1587 qdf_mem_free(tmp_assoc_req); 1588 tmp_assoc_req = NULL; 1589 } 1590 1591 session->parsedAssocReq[sta_ds->assocId] = assoc_req; 1592 *assoc_req_copied = true; 1593 } 1594 if (!assoc_req->wmeInfoPresent) { 1595 sta_ds->mlmStaContext.htCapability = 0; 1596 sta_ds->mlmStaContext.vhtCapability = 0; 1597 } else { 1598 sta_ds->mlmStaContext.htCapability = assoc_req->HTCaps.present; 1599 if ((vht_caps) && vht_caps->present) 1600 sta_ds->mlmStaContext.vhtCapability = vht_caps->present; 1601 else 1602 sta_ds->mlmStaContext.vhtCapability = false; 1603 } 1604 1605 lim_update_stads_he_capable(sta_ds, assoc_req); 1606 lim_update_stads_eht_capable(sta_ds, assoc_req); 1607 sta_ds->qos.addtsPresent = 1608 (assoc_req->addtsPresent == 0) ? false : true; 1609 sta_ds->qos.addts = assoc_req->addtsReq; 1610 sta_ds->qos.capability = assoc_req->qosCapability; 1611 /* 1612 * short slot and short preamble should be updated before doing 1613 * limaddsta 1614 */ 1615 sta_ds->shortPreambleEnabled = 1616 (uint8_t) assoc_req->capabilityInfo.shortPreamble; 1617 sta_ds->shortSlotTimeEnabled = 1618 (uint8_t) assoc_req->capabilityInfo.shortSlotTime; 1619 1620 sta_ds->valid = 0; 1621 sta_ds->mlmStaContext.authType = auth_type; 1622 sta_ds->mlmStaContext.akm_type = akm_type; 1623 sta_ds->staType = STA_ENTRY_PEER; 1624 sta_ds->mlmStaContext.force_1x1 = force_1x1; 1625 1626 pe_debug("auth_type = %d, akm_type = %d", auth_type, akm_type); 1627 1628 /* 1629 * TODO: If listen interval is more than certain limit, reject the 1630 * association. Need to check customer requirements and then implement. 1631 */ 1632 sta_ds->mlmStaContext.listenInterval = assoc_req->listenInterval; 1633 sta_ds->mlmStaContext.capabilityInfo = assoc_req->capabilityInfo; 1634 1635 if (IS_DOT11_MODE_HT(session->dot11mode) && 1636 sta_ds->mlmStaContext.htCapability) { 1637 sta_ds->htGreenfield = (uint8_t) assoc_req->HTCaps.greenField; 1638 sta_ds->htAMpduDensity = assoc_req->HTCaps.mpduDensity; 1639 sta_ds->htDsssCckRate40MHzSupport = 1640 (uint8_t) assoc_req->HTCaps.dsssCckMode40MHz; 1641 sta_ds->htLsigTXOPProtection = 1642 (uint8_t) assoc_req->HTCaps.lsigTXOPProtection; 1643 sta_ds->htMaxAmsduLength = 1644 (uint8_t) assoc_req->HTCaps.maximalAMSDUsize; 1645 sta_ds->htMaxRxAMpduFactor = assoc_req->HTCaps.maxRxAMPDUFactor; 1646 sta_ds->htMIMOPSState = assoc_req->HTCaps.mimoPowerSave; 1647 1648 /* assoc_req will be copied to session->parsedAssocReq later */ 1649 ht_cap_ie = ((uint8_t *) &assoc_req->HTCaps) + 1; 1650 1651 if (session->ht_config.short_gi_20_mhz) { 1652 sta_ds->htShortGI20Mhz = 1653 (uint8_t)assoc_req->HTCaps.shortGI20MHz; 1654 } else { 1655 /* Unset htShortGI20Mhz in ht_caps*/ 1656 *ht_cap_ie &= ~(1 << SIR_MAC_HT_CAP_SHORTGI20MHZ_S); 1657 sta_ds->htShortGI20Mhz = 0; 1658 } 1659 1660 if (session->ht_config.short_gi_40_mhz) { 1661 sta_ds->htShortGI40Mhz = 1662 (uint8_t)assoc_req->HTCaps.shortGI40MHz; 1663 } else { 1664 /* Unset htShortGI40Mhz in ht_caps */ 1665 *ht_cap_ie &= ~(1 << SIR_MAC_HT_CAP_SHORTGI40MHZ_S); 1666 sta_ds->htShortGI40Mhz = 0; 1667 } 1668 1669 sta_ds->htSupportedChannelWidthSet = 1670 (uint8_t) assoc_req->HTCaps.supportedChannelWidthSet; 1671 if (session->ch_width > CH_WIDTH_20MHZ && 1672 session->ch_width <= CH_WIDTH_80P80MHZ && 1673 sta_ds->htSupportedChannelWidthSet) { 1674 /* 1675 * peer just follows AP; so when we are softAP/GO, 1676 * we just store our session entry's secondary channel 1677 * offset here in peer INFRA STA. However, if peer's 1678 * 40MHz channel width support is disabled then 1679 * secondary channel will be zero 1680 */ 1681 sta_ds->htSecondaryChannelOffset = 1682 session->htSecondaryChannelOffset; 1683 sta_ds->ch_width = CH_WIDTH_40MHZ; 1684 if (sta_ds->mlmStaContext.vhtCapability) { 1685 if (assoc_req->operMode.present) { 1686 sta_ds->ch_width = 1687 assoc_req->operMode.chanWidth; 1688 } else if (vht_caps->supportedChannelWidthSet == 1689 VHT_CAP_160_AND_80P80_SUPP) { 1690 sta_ds->ch_width = CH_WIDTH_80P80MHZ; 1691 } else if (vht_caps->supportedChannelWidthSet == 1692 VHT_CAP_160_SUPP) { 1693 if (vht_caps->vht_extended_nss_bw_cap && 1694 vht_caps->extended_nss_bw_supp) 1695 sta_ds->ch_width = 1696 CH_WIDTH_80P80MHZ; 1697 else 1698 sta_ds->ch_width = 1699 CH_WIDTH_160MHZ; 1700 } else if (vht_caps->vht_extended_nss_bw_cap) { 1701 if (vht_caps->extended_nss_bw_supp == 1702 VHT_EXTD_NSS_80_HALF_NSS_160) 1703 sta_ds->ch_width = 1704 CH_WIDTH_160MHZ; 1705 else if (vht_caps->extended_nss_bw_supp > 1706 VHT_EXTD_NSS_80_HALF_NSS_160) 1707 sta_ds->ch_width = 1708 CH_WIDTH_80P80MHZ; 1709 else 1710 sta_ds->ch_width = 1711 CH_WIDTH_80MHZ; 1712 } else { 1713 sta_ds->ch_width = CH_WIDTH_80MHZ; 1714 } 1715 1716 sta_ds->ch_width = QDF_MIN(sta_ds->ch_width, 1717 session->ch_width); 1718 } 1719 } else { 1720 sta_ds->htSupportedChannelWidthSet = 0; 1721 sta_ds->htSecondaryChannelOffset = 0; 1722 sta_ds->ch_width = CH_WIDTH_20MHZ; 1723 } 1724 sta_ds->htLdpcCapable = 1725 (uint8_t) assoc_req->HTCaps.advCodingCap; 1726 } 1727 1728 if (assoc_req->ExtCap.present) 1729 sta_ds->non_ecsa_capable = 1730 !((struct s_ext_cap *)assoc_req->ExtCap.bytes)-> 1731 ext_chan_switch; 1732 else 1733 sta_ds->non_ecsa_capable = 1; 1734 1735 if (sta_ds->mlmStaContext.vhtCapability && 1736 session->vhtCapability) { 1737 sta_ds->htMaxRxAMpduFactor = 1738 vht_caps->maxAMPDULenExp; 1739 sta_ds->vhtLdpcCapable = 1740 (uint8_t)vht_caps->ldpcCodingCap; 1741 if (session->vht_config.su_beam_formee && 1742 vht_caps->suBeamFormerCap) 1743 sta_ds->vhtBeamFormerCapable = 1; 1744 else 1745 sta_ds->vhtBeamFormerCapable = 0; 1746 if (session->vht_config.su_beam_former && 1747 vht_caps->suBeamformeeCap) 1748 sta_ds->vht_su_bfee_capable = 1; 1749 else 1750 sta_ds->vht_su_bfee_capable = 0; 1751 1752 pe_debug("peer_caps: suBformer: %d, suBformee: %d", 1753 vht_caps->suBeamFormerCap, 1754 vht_caps->suBeamformeeCap); 1755 pe_debug("self_cap: suBformer: %d, suBformee: %d", 1756 session->vht_config.su_beam_former, 1757 session->vht_config.su_beam_formee); 1758 pe_debug("connection's final cap: suBformer: %d, suBformee: %d", 1759 sta_ds->vhtBeamFormerCapable, 1760 sta_ds->vht_su_bfee_capable); 1761 } 1762 1763 sta_ds->vht_mcs_10_11_supp = 0; 1764 if (IS_DOT11_MODE_HT(session->dot11mode) && 1765 sta_ds->mlmStaContext.vhtCapability) { 1766 if (mac_ctx->mlme_cfg->vht_caps.vht_cap_info. 1767 vht_mcs_10_11_supp && 1768 assoc_req->qcn_ie.present && 1769 assoc_req->qcn_ie.vht_mcs11_attr.present) 1770 sta_ds->vht_mcs_10_11_supp = 1771 assoc_req->qcn_ie.vht_mcs11_attr. 1772 vht_mcs_10_11_supp; 1773 } 1774 lim_intersect_sta_he_caps(mac_ctx, assoc_req, session, sta_ds); 1775 1776 lim_intersect_sta_eht_caps(mac_ctx, assoc_req, session, sta_ds); 1777 1778 lim_mlo_set_mld_mac_peer(sta_ds, assoc_req->mld_mac); 1779 1780 lim_mlo_save_mlo_info(sta_ds, &assoc_req->mlo_info); 1781 1782 if (lim_populate_matching_rate_set(mac_ctx, sta_ds, 1783 &(assoc_req->supportedRates), 1784 &(assoc_req->extendedRates), 1785 assoc_req->HTCaps.supportedMCSSet, 1786 session, vht_caps, &assoc_req->he_cap, 1787 &assoc_req->eht_cap) != QDF_STATUS_SUCCESS) { 1788 /* Could not update hash table entry at DPH with rateset */ 1789 pe_err("Couldn't update hash entry for aid: %d MacAddr: " 1790 QDF_MAC_ADDR_FMT, 1791 peer_idx, QDF_MAC_ADDR_REF(sa)); 1792 1793 /* Release AID */ 1794 if (lim_is_mlo_conn(session, sta_ds)) { 1795 if (lim_is_mlo_recv_assoc(sta_ds)) 1796 lim_release_mlo_conn_idx(mac_ctx, peer_idx, 1797 session, true); 1798 else 1799 lim_release_mlo_conn_idx(mac_ctx, peer_idx, 1800 session, false); 1801 } else { 1802 lim_release_peer_idx(mac_ctx, peer_idx, session); 1803 } 1804 1805 lim_reject_association(mac_ctx, sa, sub_type, true, 1806 auth_type, peer_idx, false, 1807 STATUS_UNSPECIFIED_FAILURE, session); 1808 pe_err("Delete dph hash entry"); 1809 if (dph_delete_hash_entry(mac_ctx, sa, sta_ds->assocId, 1810 &session->dph.dphHashTable) != 1811 QDF_STATUS_SUCCESS) 1812 pe_err("error deleting hash entry"); 1813 return false; 1814 } 1815 if (assoc_req->operMode.present) { 1816 sta_ds->vhtSupportedRxNss = assoc_req->operMode.rxNSS + 1; 1817 } else { 1818 sta_ds->vhtSupportedRxNss = 1819 ((sta_ds->supportedRates.vhtTxMCSMap & MCSMAPMASK2x2) 1820 == MCSMAPMASK2x2) ? 1 : 2; 1821 } 1822 lim_update_stads_he_6ghz_op(session, sta_ds); 1823 lim_update_sta_ds_op_classes(assoc_req, sta_ds); 1824 lim_update_stads_eht_bw_320mhz(session, sta_ds); 1825 1826 /* Add STA context at MAC HW (BMU, RHP & TFP) */ 1827 sta_ds->qosMode = false; 1828 sta_ds->lleEnabled = false; 1829 if (assoc_req->capabilityInfo.qos && (qos_mode == eHAL_SET)) { 1830 sta_ds->lleEnabled = true; 1831 sta_ds->qosMode = true; 1832 } 1833 1834 sta_ds->wmeEnabled = false; 1835 sta_ds->wsmEnabled = false; 1836 limGetWmeMode(session, &wme_mode); 1837 if ((!sta_ds->lleEnabled) && assoc_req->wmeInfoPresent 1838 && (wme_mode == eHAL_SET)) { 1839 sta_ds->wmeEnabled = true; 1840 sta_ds->qosMode = true; 1841 limGetWsmMode(session, &wsm_mode); 1842 /* 1843 * WMM_APSD - WMM_SA related processing should be separate; 1844 * WMM_SA and WMM_APSD can coexist 1845 */ 1846 if (assoc_req->WMMInfoStation.present) { 1847 /* check whether AP supports or not */ 1848 if (LIM_IS_AP_ROLE(session) && 1849 (session->apUapsdEnable == 0) && 1850 (assoc_req->WMMInfoStation.acbe_uapsd || 1851 assoc_req->WMMInfoStation.acbk_uapsd || 1852 assoc_req->WMMInfoStation.acvo_uapsd || 1853 assoc_req->WMMInfoStation.acvi_uapsd)) { 1854 /* 1855 * Rcvd Re/Assoc Req from STA when UPASD is 1856 * not supported. 1857 */ 1858 pe_err("UAPSD not supported, reply accordingly"); 1859 /* update UAPSD and send it to LIM to add STA */ 1860 sta_ds->qos.capability.qosInfo.acbe_uapsd = 0; 1861 sta_ds->qos.capability.qosInfo.acbk_uapsd = 0; 1862 sta_ds->qos.capability.qosInfo.acvo_uapsd = 0; 1863 sta_ds->qos.capability.qosInfo.acvi_uapsd = 0; 1864 sta_ds->qos.capability.qosInfo.maxSpLen = 0; 1865 } else { 1866 /* update UAPSD and send it to LIM to add STA */ 1867 sta_ds->qos.capability.qosInfo.acbe_uapsd = 1868 assoc_req->WMMInfoStation.acbe_uapsd; 1869 sta_ds->qos.capability.qosInfo.acbk_uapsd = 1870 assoc_req->WMMInfoStation.acbk_uapsd; 1871 sta_ds->qos.capability.qosInfo.acvo_uapsd = 1872 assoc_req->WMMInfoStation.acvo_uapsd; 1873 sta_ds->qos.capability.qosInfo.acvi_uapsd = 1874 assoc_req->WMMInfoStation.acvi_uapsd; 1875 sta_ds->qos.capability.qosInfo.maxSpLen = 1876 assoc_req->WMMInfoStation.max_sp_length; 1877 } 1878 } 1879 if (assoc_req->wsmCapablePresent && (wsm_mode == eHAL_SET)) 1880 sta_ds->wsmEnabled = true; 1881 } 1882 /* Re/Assoc Response frame to requesting STA */ 1883 sta_ds->mlmStaContext.subType = sub_type; 1884 1885 sta_ds->rmfEnabled = (pmf_connection) ? 1 : 0; 1886 sta_ds->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS; 1887 timer_id.fields.sessionId = session->peSessionId; 1888 timer_id.fields.peerIdx = peer_idx; 1889 retry_interval = mac_ctx->mlme_cfg->gen.pmf_sa_query_retry_interval; 1890 if (cfg_min(CFG_PMF_SA_QUERY_RETRY_INTERVAL) > retry_interval) { 1891 retry_interval = cfg_default(CFG_PMF_SA_QUERY_RETRY_INTERVAL); 1892 } 1893 if (sta_ds->rmfEnabled) { 1894 sta_ds->ocv_enabled = lim_is_ocv_enable_in_assoc_req(mac_ctx, 1895 assoc_req); 1896 if (sta_ds->ocv_enabled) 1897 sta_ds->last_ocv_done_freq = session->curr_op_freq; 1898 /* Try to delete it before, creating.*/ 1899 lim_delete_pmf_query_timer(sta_ds); 1900 if (tx_timer_create(mac_ctx, &sta_ds->pmfSaQueryTimer, 1901 "PMF SA Query timer", lim_pmf_sa_query_timer_handler, 1902 timer_id.value, 1903 SYS_MS_TO_TICKS((retry_interval * 1024) / 1000), 1904 0, TX_NO_ACTIVATE) != TX_SUCCESS) { 1905 pe_err("could not create PMF SA Query timer"); 1906 lim_reject_association(mac_ctx, sa, sub_type, 1907 true, auth_type, peer_idx, false, 1908 STATUS_UNSPECIFIED_FAILURE, 1909 session); 1910 return false; 1911 } 1912 pe_debug("Created pmf timer assoc-id:%d sta mac" QDF_MAC_ADDR_FMT, 1913 sta_ds->assocId, QDF_MAC_ADDR_REF(sta_ds->staAddr)); 1914 } 1915 1916 if (assoc_req->ExtCap.present) { 1917 lim_set_stads_rtt_cap(sta_ds, 1918 (struct s_ext_cap *) assoc_req->ExtCap.bytes, mac_ctx); 1919 } else { 1920 sta_ds->timingMeasCap = 0; 1921 pe_debug("ExtCap not present"); 1922 } 1923 lim_ap_check_6g_compatible_peer(mac_ctx, session); 1924 return true; 1925 } 1926 1927 /** 1928 * lim_update_sta_ctx() - add/del sta depending on connection state machine 1929 * @mac_ctx: pointer to Global MAC structure 1930 * @session: pointer to pe session entry 1931 * @assoc_req: pointer to ASSOC/REASSOC Request frame 1932 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe 1933 * @sta_ds: station dph entry 1934 * @update_ctx: indicates if STA context already exist 1935 * 1936 * Checks for SSID match 1937 * 1938 * Return: true of no error, false otherwise 1939 */ lim_update_sta_ctx(struct mac_context * mac_ctx,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,tpDphHashNode sta_ds,uint8_t update_ctx)1940 static bool lim_update_sta_ctx(struct mac_context *mac_ctx, struct pe_session *session, 1941 tpSirAssocReq assoc_req, uint8_t sub_type, 1942 tpDphHashNode sta_ds, uint8_t update_ctx) 1943 { 1944 tLimMlmStates mlm_prev_state; 1945 /* 1946 * BTAMP: If STA context already exist (ie. update_ctx = 1) for this STA 1947 * then we should delete the old one, and add the new STA. This is taken 1948 * care of in the lim_del_sta() routine. 1949 * 1950 * Prior to BTAMP, we were setting this flag so that when PE receives 1951 * SME_ASSOC_CNF, and if this flag is set, then PE shall delete the old 1952 * station and then add. But now in BTAMP, we're directly adding station 1953 * before waiting for SME_ASSOC_CNF, so we can do this now. 1954 */ 1955 if (!(update_ctx)) { 1956 sta_ds->mlmStaContext.updateContext = 0; 1957 1958 /* 1959 * BTAMP: Add STA context at HW - issue WMA_ADD_STA_REQ to HAL 1960 */ 1961 if (lim_add_sta(mac_ctx, sta_ds, false, session) != 1962 QDF_STATUS_SUCCESS) { 1963 pe_err("could not Add STA with assocId: %d", 1964 sta_ds->assocId); 1965 lim_reject_association(mac_ctx, sta_ds->staAddr, 1966 sta_ds->mlmStaContext.subType, true, 1967 sta_ds->mlmStaContext.authType, 1968 sta_ds->assocId, true, 1969 STATUS_UNSPECIFIED_FAILURE, 1970 session); 1971 1972 if (session->parsedAssocReq) 1973 assoc_req = 1974 session->parsedAssocReq[sta_ds->assocId]; 1975 return false; 1976 } 1977 } else { 1978 sta_ds->mlmStaContext.updateContext = 1; 1979 mlm_prev_state = sta_ds->mlmStaContext.mlmState; 1980 1981 /* 1982 * As per the HAL/FW needs the reassoc req need not be calling 1983 * lim_del_sta 1984 */ 1985 if (sub_type != LIM_REASSOC) { 1986 /* 1987 * we need to set the mlmState here in order 1988 * differentiate in lim_del_sta. 1989 */ 1990 sta_ds->mlmStaContext.mlmState = 1991 eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE; 1992 if (lim_del_sta(mac_ctx, sta_ds, true, session) 1993 != QDF_STATUS_SUCCESS) { 1994 pe_err("Couldn't DEL STA, assocId: %d sta mac" 1995 QDF_MAC_ADDR_FMT, sta_ds->assocId, 1996 QDF_MAC_ADDR_REF(sta_ds->staAddr)); 1997 lim_reject_association(mac_ctx, sta_ds->staAddr, 1998 sta_ds->mlmStaContext.subType, true, 1999 sta_ds->mlmStaContext.authType, 2000 sta_ds->assocId, true, 2001 STATUS_UNSPECIFIED_FAILURE, 2002 session); 2003 2004 /* Restoring the state back. */ 2005 sta_ds->mlmStaContext.mlmState = mlm_prev_state; 2006 if (session->parsedAssocReq) 2007 assoc_req = session->parsedAssocReq[ 2008 sta_ds->assocId]; 2009 return false; 2010 } 2011 } else { 2012 /* 2013 * mlmState is changed in lim_add_sta context use the 2014 * same AID, already allocated 2015 */ 2016 if (lim_add_sta(mac_ctx, sta_ds, false, session) 2017 != QDF_STATUS_SUCCESS) { 2018 pe_err("UPASD not supported, REASSOC Failed"); 2019 lim_reject_association(mac_ctx, sta_ds->staAddr, 2020 sta_ds->mlmStaContext.subType, true, 2021 sta_ds->mlmStaContext.authType, 2022 sta_ds->assocId, true, 2023 STATUS_TDLS_WAKEUP_REJECT, 2024 session); 2025 2026 /* Restoring the state back. */ 2027 sta_ds->mlmStaContext.mlmState = mlm_prev_state; 2028 if (session->parsedAssocReq) 2029 assoc_req = session->parsedAssocReq[ 2030 sta_ds->assocId]; 2031 return false; 2032 } 2033 } 2034 } 2035 return true; 2036 } 2037 lim_process_assoc_cleanup(struct mac_context * mac_ctx,struct pe_session * session,tpSirAssocReq assoc_req,tpDphHashNode sta_ds,bool assoc_req_copied)2038 void lim_process_assoc_cleanup(struct mac_context *mac_ctx, 2039 struct pe_session *session, 2040 tpSirAssocReq assoc_req, 2041 tpDphHashNode sta_ds, 2042 bool assoc_req_copied) 2043 { 2044 tpSirAssocReq tmp_assoc_req; 2045 2046 if (assoc_req) { 2047 lim_free_assoc_req_frm_buf(assoc_req); 2048 2049 qdf_mem_free(assoc_req); 2050 /* to avoid double free */ 2051 if (assoc_req_copied && session->parsedAssocReq && sta_ds) 2052 session->parsedAssocReq[sta_ds->assocId] = NULL; 2053 } 2054 2055 /* If it is not duplicate Assoc request then only make to Null */ 2056 if ((sta_ds) && 2057 (sta_ds->mlmStaContext.mlmState != eLIM_MLM_WT_ADD_STA_RSP_STATE)) { 2058 if (session->parsedAssocReq) { 2059 tmp_assoc_req = 2060 session->parsedAssocReq[sta_ds->assocId]; 2061 if (tmp_assoc_req) { 2062 lim_free_assoc_req_frm_buf(tmp_assoc_req); 2063 qdf_mem_free(tmp_assoc_req); 2064 session->parsedAssocReq[sta_ds->assocId] = NULL; 2065 } 2066 } 2067 } 2068 } 2069 2070 /** 2071 * lim_defer_sme_indication() - Defer assoc indication to SME 2072 * @mac_ctx: Pointer to Global MAC structure 2073 * @session: pe session entry 2074 * @sub_type: Indicates whether it is Association Request(=0) or Reassociation 2075 * Request(=1) frame 2076 * @sa: Mac address of requesting peer 2077 * @assoc_req: pointer to ASSOC/REASSOC Request frame 2078 * @pmf_connection: flag indicating pmf connection 2079 * @assoc_req_copied: boolean to indicate if assoc req was copied to tmp above 2080 * @dup_entry: flag indicating if duplicate entry found 2081 * @partner_peer_idx: association id allocated by partner peer 2082 * 2083 * Defer Initialization of PE data structures and wait for an external event. 2084 * lim_send_assoc_ind_to_sme() will be called to initialize PE data structures 2085 * when the expected event is received. 2086 * 2087 * Return: void 2088 */ lim_defer_sme_indication(struct mac_context * mac_ctx,struct pe_session * session,uint8_t sub_type,tSirMacAddr sa,struct sSirAssocReq * assoc_req,bool pmf_connection,bool assoc_req_copied,bool dup_entry,struct sDphHashNode * sta_ds,uint16_t partner_peer_idx)2089 static void lim_defer_sme_indication(struct mac_context *mac_ctx, 2090 struct pe_session *session, 2091 uint8_t sub_type, 2092 tSirMacAddr sa, 2093 struct sSirAssocReq *assoc_req, 2094 bool pmf_connection, 2095 bool assoc_req_copied, 2096 bool dup_entry, 2097 struct sDphHashNode *sta_ds, 2098 uint16_t partner_peer_idx) 2099 { 2100 struct tLimPreAuthNode *sta_pre_auth_ctx; 2101 struct lim_assoc_data *cached_req; 2102 2103 /* Extract pre-auth context for the STA, if any. */ 2104 sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx, sa); 2105 if (sta_pre_auth_ctx->assoc_req.present) { 2106 pe_debug("Free the cached assoc req as a new one is received"); 2107 cached_req = &sta_pre_auth_ctx->assoc_req; 2108 lim_process_assoc_cleanup(mac_ctx, session, 2109 cached_req->assoc_req, 2110 cached_req->sta_ds, 2111 cached_req->assoc_req_copied); 2112 } 2113 2114 sta_pre_auth_ctx->assoc_req.present = true; 2115 sta_pre_auth_ctx->assoc_req.sub_type = sub_type; 2116 qdf_mem_copy(sta_pre_auth_ctx->assoc_req.sa, sa, 2117 sizeof(sta_pre_auth_ctx->assoc_req.sa)); 2118 sta_pre_auth_ctx->assoc_req.assoc_req = assoc_req; 2119 sta_pre_auth_ctx->assoc_req.pmf_connection = pmf_connection; 2120 sta_pre_auth_ctx->assoc_req.assoc_req_copied = assoc_req_copied; 2121 sta_pre_auth_ctx->assoc_req.dup_entry = dup_entry; 2122 sta_pre_auth_ctx->assoc_req.sta_ds = sta_ds; 2123 sta_pre_auth_ctx->assoc_req.partner_peer_idx = partner_peer_idx; 2124 } 2125 lim_is_sae_akm_present(tDot11fIERSN * const rsn_ie)2126 static bool lim_is_sae_akm_present(tDot11fIERSN * const rsn_ie) 2127 { 2128 uint16_t i; 2129 2130 if (rsn_ie->akm_suite_cnt > 6) 2131 return false; 2132 2133 for (i = 0; i < rsn_ie->akm_suite_cnt; i++) { 2134 if ((LE_READ_4(rsn_ie->akm_suite[i]) == RSN_AUTH_KEY_MGMT_SAE) || 2135 (LE_READ_4(rsn_ie->akm_suite[i]) == 2136 RSN_AUTH_KEY_MGMT_SAE_EXT_KEY)) { 2137 pe_debug("SAE AKM present"); 2138 return true; 2139 } 2140 } 2141 return false; 2142 } 2143 lim_is_pmkid_found_for_peer(struct mac_context * mac_ctx,tSirMacAddr peer_mac_addr,struct pe_session * session,uint8_t * pmkid,uint16_t pmkid_count)2144 static bool lim_is_pmkid_found_for_peer(struct mac_context *mac_ctx, 2145 tSirMacAddr peer_mac_addr, 2146 struct pe_session *session, 2147 uint8_t *pmkid, 2148 uint16_t pmkid_count) 2149 { 2150 uint32_t i; 2151 uint8_t *session_pmkid; 2152 struct wlan_crypto_pmksa *pmkid_cache; 2153 2154 pmkid_cache = qdf_mem_malloc(sizeof(*pmkid_cache)); 2155 2156 if (!pmkid_cache) 2157 return false; 2158 2159 qdf_mem_copy(pmkid_cache->bssid.bytes, peer_mac_addr, 2160 QDF_MAC_ADDR_SIZE); 2161 2162 if (!cm_lookup_pmkid_using_bssid(mac_ctx->psoc, session->vdev_id, 2163 pmkid_cache)) { 2164 qdf_mem_free(pmkid_cache); 2165 return false; 2166 } 2167 2168 session_pmkid = pmkid_cache->pmkid; 2169 for (i = 0; i < pmkid_count; i++) { 2170 if (!qdf_mem_cmp(pmkid + (i * PMKID_LEN), 2171 session_pmkid, PMKID_LEN)) { 2172 qdf_mem_free(pmkid_cache); 2173 return true; 2174 } 2175 } 2176 2177 pe_debug("PMKID in cache doesn't match with PMKIDs from the peer"); 2178 qdf_mem_free(pmkid_cache); 2179 2180 return false; 2181 } 2182 lim_is_sae_peer_allowed(struct mac_context * mac_ctx,struct pe_session * session,tDot11fIERSN * rsn_ie,tSirMacAddr sa,enum wlan_status_code * mac_status_code)2183 static bool lim_is_sae_peer_allowed(struct mac_context *mac_ctx, 2184 struct pe_session *session, 2185 tDot11fIERSN *rsn_ie, tSirMacAddr sa, 2186 enum wlan_status_code *mac_status_code) 2187 { 2188 bool is_allowed = false; 2189 uint8_t *peer_mac_addr = sa; 2190 2191 /* Allow the peer with valid PMKID */ 2192 if (!rsn_ie->pmkid_count) { 2193 *mac_status_code = STATUS_NOT_SUPPORTED_AUTH_ALG; 2194 pe_debug("No PMKID present in RSNIE; Tried to use SAE AKM after non-SAE authentication"); 2195 } else if (lim_is_pmkid_found_for_peer(mac_ctx, peer_mac_addr, session, 2196 &rsn_ie->pmkid[0][0], 2197 rsn_ie->pmkid_count)) { 2198 pe_debug("Valid PMKID found for SAE peer"); 2199 is_allowed = true; 2200 } else { 2201 *mac_status_code = STATUS_INVALID_PMKID; 2202 pe_debug("No valid PMKID found for SAE peer"); 2203 } 2204 2205 return is_allowed; 2206 } 2207 lim_validate_pmkid_for_sae(struct mac_context * mac_ctx,struct pe_session * session,tpSirAssocReq assoc_req,tSirMacAddr sa,uint8_t sub_type)2208 static bool lim_validate_pmkid_for_sae(struct mac_context *mac_ctx, 2209 struct pe_session *session, 2210 tpSirAssocReq assoc_req, tSirMacAddr sa, 2211 uint8_t sub_type) 2212 { 2213 tDot11fIERSN rsn_ie = {0}; 2214 enum wlan_status_code code = STATUS_INVALID_IE; 2215 2216 if (!assoc_req->rsnPresent) 2217 return true; 2218 2219 if (dot11f_unpack_ie_rsn(mac_ctx, &assoc_req->rsn.info[0], 2220 assoc_req->rsn.length, 2221 &rsn_ie, false) != DOT11F_PARSE_SUCCESS) 2222 goto reject_assoc; 2223 2224 if (lim_is_sae_akm_present(&rsn_ie) && 2225 !assoc_req->is_sae_authenticated && 2226 !lim_is_sae_peer_allowed(mac_ctx, session, &rsn_ie, sa, &code)) 2227 goto reject_assoc; 2228 2229 return true; 2230 2231 reject_assoc: 2232 lim_send_assoc_rsp_mgmt_frame(mac_ctx, code, 1, sa, sub_type, 0, 2233 session, false); 2234 return false; 2235 } 2236 lim_send_assoc_ind_to_sme(struct mac_context * mac_ctx,struct pe_session * session,uint8_t sub_type,tSirMacAddr sa,tpSirAssocReq assoc_req,enum ani_akm_type akm_type,bool pmf_connection,bool * assoc_req_copied,bool dup_entry,bool force_1x1,uint16_t partner_peer_idx)2237 bool lim_send_assoc_ind_to_sme(struct mac_context *mac_ctx, 2238 struct pe_session *session, 2239 uint8_t sub_type, tSirMacAddr sa, 2240 tpSirAssocReq assoc_req, 2241 enum ani_akm_type akm_type, 2242 bool pmf_connection, bool *assoc_req_copied, 2243 bool dup_entry, bool force_1x1, 2244 uint16_t partner_peer_idx) 2245 { 2246 uint16_t peer_idx; 2247 struct tLimPreAuthNode *sta_pre_auth_ctx; 2248 tpDphHashNode sta_ds = NULL; 2249 tHalBitVal qos_mode; 2250 tAniAuthType auth_type; 2251 uint8_t update_ctx = false; 2252 2253 limGetQosMode(session, &qos_mode); 2254 /* Extract 'associated' context for STA, if any. */ 2255 sta_ds = dph_lookup_hash_entry(mac_ctx, sa, &peer_idx, 2256 &session->dph.dphHashTable); 2257 2258 /* Extract pre-auth context for the STA, if any. */ 2259 sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx, sa); 2260 2261 if (!sta_ds) { 2262 if (!lim_process_assoc_req_no_sta_ctx(mac_ctx, sa, session, 2263 assoc_req, sub_type, 2264 sta_pre_auth_ctx, sta_ds, 2265 &auth_type, 2266 partner_peer_idx)) 2267 return false; 2268 } else { 2269 if (!lim_process_assoc_req_sta_ctx(mac_ctx, sa, session, 2270 assoc_req, sub_type, 2271 sta_pre_auth_ctx, sta_ds, 2272 peer_idx, &auth_type, 2273 &update_ctx)) 2274 return false; 2275 goto send_ind_to_sme; 2276 } 2277 2278 if (LIM_IS_AP_ROLE(session)) { 2279 if ((assoc_req->wpaPresent || assoc_req->rsnPresent) && 2280 !session->privacy) { 2281 pe_debug("reject assoc. wpa: %d, rsn: %d, privacy: %d", 2282 assoc_req->wpaPresent, 2283 assoc_req->rsnPresent, 2284 session->privacy); 2285 lim_reject_association(mac_ctx, sa, sub_type, true, 2286 auth_type, peer_idx, false, 2287 STATUS_UNSPECIFIED_FAILURE, 2288 session); 2289 return false; 2290 } 2291 } 2292 2293 /* check if sta is allowed per QoS AC rules */ 2294 if (!lim_chk_wmm(mac_ctx, sa, session, assoc_req, sub_type, qos_mode)) 2295 return false; 2296 2297 if (!lim_validate_pmkid_for_sae(mac_ctx, session, assoc_req, 2298 sa, sub_type)) 2299 return false; 2300 2301 /* STA is Associated ! */ 2302 pe_debug("Received: %s Req successful from " QDF_MAC_ADDR_FMT, 2303 (sub_type == LIM_ASSOC) ? "Assoc" : "ReAssoc", 2304 QDF_MAC_ADDR_REF(sa)); 2305 2306 /* 2307 * AID for this association will be same as the peer Index used in DPH 2308 * table. Assign unused/least recently used peer Index from perStaDs. 2309 * NOTE: lim_assign_peer_idx() assigns AID values ranging between 2310 * 1 - cfg_item(WNI_CFG_ASSOC_STA_LIMIT) 2311 */ 2312 2313 if (wlan_vdev_mlme_is_mlo_ap(session->vdev) && 2314 assoc_req->eht_cap.present && 2315 IS_DOT11_MODE_EHT(session->dot11mode) && 2316 (partner_peer_idx || 2317 !qdf_is_macaddr_zero((struct qdf_mac_addr *)assoc_req->mld_mac))) 2318 peer_idx = lim_assign_mlo_conn_idx(mac_ctx, session, 2319 partner_peer_idx); 2320 else 2321 peer_idx = lim_assign_peer_idx(mac_ctx, session); 2322 2323 if (!peer_idx && !partner_peer_idx) { 2324 /* Could not assign AID. Reject association */ 2325 pe_err("PeerIdx not available. Reject associaton"); 2326 lim_reject_association(mac_ctx, sa, sub_type, 2327 true, auth_type, peer_idx, false, 2328 STATUS_UNSPECIFIED_FAILURE, 2329 session); 2330 return false; 2331 } else if (!peer_idx) { 2332 pe_err("mlo partner PeerIdx not available. Reject associaton"); 2333 lim_send_sme_max_assoc_exceeded_ntf(mac_ctx, sa, 2334 session->smeSessionId); 2335 return false; 2336 } 2337 2338 /* Add an entry to hash table maintained by DPH module */ 2339 2340 sta_ds = dph_add_hash_entry(mac_ctx, sa, peer_idx, 2341 &session->dph.dphHashTable); 2342 2343 if (!sta_ds && !partner_peer_idx) { 2344 /* Could not add hash table entry at DPH */ 2345 pe_err("couldn't add hash entry at DPH for aid: %d MacAddr:" 2346 QDF_MAC_ADDR_FMT, peer_idx, QDF_MAC_ADDR_REF(sa)); 2347 2348 /* Release AID */ 2349 if (wlan_vdev_mlme_is_mlo_ap(session->vdev) && 2350 assoc_req->eht_cap.present && 2351 IS_DOT11_MODE_EHT(session->dot11mode) && 2352 (partner_peer_idx || assoc_req->mlo_info.num_partner_links)) 2353 lim_release_mlo_conn_idx(mac_ctx, peer_idx, session, 2354 true); 2355 else 2356 lim_release_peer_idx(mac_ctx, peer_idx, session); 2357 2358 lim_reject_association(mac_ctx, sa, sub_type, 2359 true, auth_type, peer_idx, false, 2360 STATUS_UNSPECIFIED_FAILURE, 2361 session); 2362 return false; 2363 } else if (!sta_ds) { 2364 pe_err("mlo partner peer couldn't add hash entry at DPH for aid: %d MacAddr:" 2365 QDF_MAC_ADDR_FMT, peer_idx, QDF_MAC_ADDR_REF(sa)); 2366 lim_send_sme_max_assoc_exceeded_ntf(mac_ctx, sa, 2367 session->smeSessionId); 2368 return false; 2369 } 2370 2371 /*only mlo partner peer get valid aid before proc assoc req*/ 2372 if (!partner_peer_idx) 2373 lim_set_mlo_recv_assoc(sta_ds, true); 2374 else 2375 lim_set_mlo_recv_assoc(sta_ds, false); 2376 2377 send_ind_to_sme: 2378 if (!lim_update_sta_ds(mac_ctx, sa, session, assoc_req, 2379 sub_type, sta_ds, auth_type, akm_type, 2380 assoc_req_copied, peer_idx, qos_mode, 2381 pmf_connection, force_1x1)) 2382 return false; 2383 2384 /* BTAMP: Storing the parsed assoc request in the session array */ 2385 if (session->parsedAssocReq) 2386 session->parsedAssocReq[sta_ds->assocId] = assoc_req; 2387 *assoc_req_copied = true; 2388 2389 /* If it is duplicate entry wait till the peer is deleted */ 2390 if (!dup_entry) { 2391 if (!lim_update_sta_ctx(mac_ctx, session, assoc_req, 2392 sub_type, sta_ds, update_ctx)) 2393 return false; 2394 } 2395 2396 /* AddSta is success here */ 2397 if (LIM_IS_AP_ROLE(session) && IS_DOT11_MODE_HT(session->dot11mode) && 2398 assoc_req->HTCaps.present && assoc_req->wmeInfoPresent) { 2399 /* 2400 * Update in the HAL Sta Table for the Update of the Protection 2401 * Mode 2402 */ 2403 lim_post_sm_state_update(mac_ctx, 2404 sta_ds->htMIMOPSState, sta_ds->staAddr, 2405 session->smeSessionId); 2406 } 2407 2408 return true; 2409 } 2410 2411 /** 2412 * lim_peer_present_on_any_sta() - Check if Same MAC is connected with STA, i.e. 2413 * duplicate mac detection. 2414 * @mac_ctx: Pointer to Global MAC structure 2415 * @peer_addr: peer address to check 2416 * 2417 * This function will return true if a peer STA and AP are using same mac 2418 * address. 2419 * 2420 * @Return: bool 2421 */ 2422 static bool lim_peer_present_on_any_sta(struct mac_context * mac_ctx,uint8_t * peer_addr)2423 lim_peer_present_on_any_sta(struct mac_context *mac_ctx, uint8_t *peer_addr) 2424 { 2425 struct wlan_objmgr_peer *peer; 2426 bool sta_peer_present = false; 2427 enum QDF_OPMODE mode; 2428 uint8_t peer_vdev_id; 2429 2430 peer = wlan_objmgr_get_peer_by_mac(mac_ctx->psoc, peer_addr, 2431 WLAN_LEGACY_MAC_ID); 2432 if (!peer) 2433 return sta_peer_present; 2434 2435 peer_vdev_id = wlan_vdev_get_id(wlan_peer_get_vdev(peer)); 2436 mode = wlan_vdev_mlme_get_opmode(wlan_peer_get_vdev(peer)); 2437 if (mode == QDF_STA_MODE || mode == QDF_P2P_CLIENT_MODE) { 2438 pe_debug("duplicate mac detected!!! Peer " QDF_MAC_ADDR_FMT " present on STA vdev %d", 2439 QDF_MAC_ADDR_REF(peer_addr), peer_vdev_id); 2440 sta_peer_present = true; 2441 } 2442 2443 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID); 2444 2445 return sta_peer_present; 2446 } 2447 lim_check_assoc_req(struct mac_context * mac_ctx,uint8_t sub_type,tSirMacAddr sa,struct pe_session * session)2448 QDF_STATUS lim_check_assoc_req(struct mac_context *mac_ctx, 2449 uint8_t sub_type, tSirMacAddr sa, 2450 struct pe_session *session) 2451 { 2452 if (LIM_IS_STA_ROLE(session)) { 2453 pe_err("Rcvd unexpected ASSOC REQ, sessionid: %d sys sub_type: %d for role: %d from: " 2454 QDF_MAC_ADDR_FMT, 2455 session->peSessionId, sub_type, 2456 GET_LIM_SYSTEM_ROLE(session), 2457 QDF_MAC_ADDR_REF(sa)); 2458 return QDF_STATUS_E_INVAL; 2459 } 2460 2461 if (session->limMlmState == eLIM_MLM_WT_DEL_BSS_RSP_STATE) { 2462 pe_err("drop ASSOC REQ on sessionid: %d role: %d from: " 2463 QDF_MAC_ADDR_FMT " in limMlmState: %d", 2464 session->peSessionId, 2465 GET_LIM_SYSTEM_ROLE(session), 2466 QDF_MAC_ADDR_REF(sa), 2467 eLIM_MLM_WT_DEL_BSS_RSP_STATE); 2468 return QDF_STATUS_E_INVAL; 2469 } 2470 2471 if (lim_peer_present_on_any_sta(mac_ctx, sa)) 2472 /* 2473 * This mean a AP and STA have same mac address and device STA 2474 * is already connected to the AP, and STA is now trying to 2475 * connect to device SAP. So ignore association. 2476 */ 2477 return QDF_STATUS_E_INVAL; 2478 2479 return QDF_STATUS_SUCCESS; 2480 } 2481 2482 #ifdef WLAN_SUPPORT_TWT 2483 /* lim_set_sap_peer_twt_cap() - Set SAP peer twt requestor and responder bit 2484 * @session: PE session handle 2485 * @ext_cap: pointer to ext cap 2486 * 2487 * This function is used to update SAP peer twt requestor and responder bit 2488 * from ext cap of assoc request received by SAP 2489 * 2490 * Return: None 2491 */ lim_set_sap_peer_twt_cap(struct pe_session * session,struct s_ext_cap * ext_cap)2492 static void lim_set_sap_peer_twt_cap(struct pe_session *session, 2493 struct s_ext_cap *ext_cap) 2494 { 2495 session->peer_twt_requestor = ext_cap->twt_requestor_support; 2496 session->peer_twt_responder = ext_cap->twt_responder_support; 2497 2498 pe_debug("Ext Cap peer TWT requestor: %d, responder: %d", 2499 ext_cap->twt_requestor_support, 2500 ext_cap->twt_responder_support); 2501 } 2502 #else 2503 static inline void lim_set_sap_peer_twt_cap(struct pe_session * session,struct s_ext_cap * ext_cap)2504 lim_set_sap_peer_twt_cap(struct pe_session *session, 2505 struct s_ext_cap *ext_cap) 2506 { 2507 } 2508 #endif 2509 2510 /* lim_update_ap_ext_cap() - Update SAP with ext capabilities 2511 * @session: PE session handle 2512 * @ assoc_req: pointer to assoc req 2513 * 2514 * This function is called by lim_proc_assoc_req_frm_cmn to 2515 * update SAP ext capabilities 2516 * 2517 * Return: None 2518 */ lim_update_ap_ext_cap(struct pe_session * session,tpSirAssocReq assoc_req)2519 static void lim_update_ap_ext_cap(struct pe_session *session, 2520 tpSirAssocReq assoc_req) 2521 { 2522 struct s_ext_cap *ext_cap; 2523 2524 ext_cap = (struct s_ext_cap *)assoc_req->ExtCap.bytes; 2525 lim_set_sap_peer_twt_cap(session, ext_cap); 2526 } 2527 lim_proc_assoc_req_frm_cmn(struct mac_context * mac_ctx,uint8_t sub_type,struct pe_session * session,tSirMacAddr sa,tpSirAssocReq assoc_req,uint16_t peer_aid)2528 QDF_STATUS lim_proc_assoc_req_frm_cmn(struct mac_context *mac_ctx, 2529 uint8_t sub_type, 2530 struct pe_session *session, 2531 tSirMacAddr sa, 2532 tpSirAssocReq assoc_req, 2533 uint16_t peer_aid) 2534 { 2535 bool pmf_connection = false, assoc_req_copied = false; 2536 uint32_t phy_mode; 2537 tHalBitVal qos_mode; 2538 struct tLimPreAuthNode *sta_pre_auth_ctx; 2539 enum ani_akm_type akm_type = ANI_AKM_TYPE_NONE; 2540 tSirMacCapabilityInfo local_cap; 2541 tpDphHashNode sta_ds = NULL; 2542 bool dup_entry = false, force_1x1 = false; 2543 QDF_STATUS status; 2544 uint8_t *frm_body; 2545 uint32_t frame_len; 2546 2547 frm_body = assoc_req->assocReqFrame; 2548 frame_len = assoc_req->assocReqFrameLength; 2549 lim_get_phy_mode(mac_ctx, &phy_mode, session); 2550 limGetQosMode(session, &qos_mode); 2551 2552 status = lim_check_sta_in_pe_entries(mac_ctx, sa, 2553 session->peSessionId, 2554 &dup_entry); 2555 if (QDF_IS_STATUS_ERROR(status)) { 2556 pe_err("Reject assoc as duplicate entry is present and is already being deleted, assoc will be accepted once deletion is completed"); 2557 /* 2558 * This mean that the duplicate entry is present on other vdev 2559 * and is already being deleted, so reject the assoc and lets 2560 * peer try again to connect, once peer is deleted from 2561 * other vdev. 2562 */ 2563 if (!peer_aid) 2564 lim_send_assoc_rsp_mgmt_frame( 2565 mac_ctx, 2566 STATUS_UNSPECIFIED_FAILURE, 2567 1, sa, 2568 sub_type, 0, session, false); 2569 goto error; 2570 } 2571 /* check for the presence of vendor IE */ 2572 if (session->access_policy_vendor_ie && 2573 session->access_policy == 2574 LIM_ACCESS_POLICY_RESPOND_IF_IE_IS_PRESENT) { 2575 if (frame_len <= LIM_ASSOC_REQ_IE_OFFSET) { 2576 pe_debug("Received action frame of invalid len %d", 2577 frame_len); 2578 goto error; 2579 } 2580 if (!wlan_get_vendor_ie_ptr_from_oui( 2581 &session->access_policy_vendor_ie[2], 2582 3, frm_body + LIM_ASSOC_REQ_IE_OFFSET, 2583 frame_len - LIM_ASSOC_REQ_IE_OFFSET)) { 2584 pe_err("Vendor ie not present and access policy is %x, Rejected association", 2585 session->access_policy); 2586 if (!peer_aid) 2587 lim_send_assoc_rsp_mgmt_frame( 2588 mac_ctx, STATUS_UNSPECIFIED_FAILURE, 2589 1, sa, sub_type, 0, session, false); 2590 goto error; 2591 } 2592 } 2593 2594 if (!lim_chk_assoc_req_parse_error(mac_ctx, sa, session, 2595 assoc_req, sub_type, 2596 frm_body, frame_len)) 2597 goto error; 2598 2599 if (!lim_chk_capab(mac_ctx, sa, session, assoc_req, 2600 sub_type, &local_cap)) 2601 goto error; 2602 2603 if (!lim_chk_ssid(mac_ctx, sa, session, assoc_req, sub_type)) 2604 goto error; 2605 2606 if (!lim_chk_rates(mac_ctx, sa, session, assoc_req, sub_type)) 2607 goto error; 2608 2609 if (!lim_chk_11g_only(mac_ctx, sa, session, assoc_req, 2610 sub_type)) 2611 goto error; 2612 2613 if (!lim_chk_11n_only(mac_ctx, sa, session, assoc_req, 2614 sub_type)) 2615 goto error; 2616 2617 if (!lim_chk_11ac_only(mac_ctx, sa, session, assoc_req, 2618 sub_type)) 2619 goto error; 2620 2621 if (!lim_chk_11ax_only(mac_ctx, sa, session, assoc_req, 2622 sub_type)) 2623 goto error; 2624 2625 if (!lim_chk_11be_only(mac_ctx, sa, session, assoc_req, 2626 sub_type)) 2627 goto error; 2628 2629 if (!lim_check_11ax_basic_mcs(mac_ctx, sa, session, assoc_req, 2630 sub_type)) 2631 goto error; 2632 2633 /* Spectrum Management (11h) specific checks */ 2634 lim_process_for_spectrum_mgmt(mac_ctx, sa, session, 2635 assoc_req, sub_type, local_cap); 2636 2637 if (!lim_chk_mcs(mac_ctx, sa, session, assoc_req, sub_type)) 2638 goto error; 2639 2640 if (!lim_chk_is_11b_sta_supported(mac_ctx, sa, session, 2641 assoc_req, sub_type, phy_mode)) 2642 goto error; 2643 2644 /* 2645 * Check for 802.11n HT caps compatibility; are HT Capabilities 2646 * turned on in lim? 2647 */ 2648 lim_print_ht_cap(mac_ctx, session, assoc_req); 2649 2650 if (!lim_chk_n_process_wpa_rsn_ie(mac_ctx, sa, session, 2651 assoc_req, sub_type, 2652 &pmf_connection, 2653 &akm_type)) 2654 goto error; 2655 2656 /* Update ap ext cap */ 2657 lim_update_ap_ext_cap(session, assoc_req); 2658 2659 /* Extract pre-auth context for the STA, if any. */ 2660 sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx, sa); 2661 2662 /* SAE authentication is offloaded to hostapd. Hostapd sends 2663 * authentication status to driver after completing SAE 2664 * authentication (after sending out 4/4 SAE auth frame). 2665 * There is a possible race condition where driver gets 2666 * assoc request from SAE station before getting authentication 2667 * status from hostapd. Don't reject the association in such 2668 * cases and defer the processing of assoc request frame by caching 2669 * the frame and process it when the auth status is received. 2670 */ 2671 if (sta_pre_auth_ctx && 2672 sta_pre_auth_ctx->authType == eSIR_AUTH_TYPE_SAE && 2673 sta_pre_auth_ctx->mlmState == eLIM_MLM_WT_SAE_AUTH_STATE) { 2674 pe_debug("Received assoc request frame while SAE authentication is in progress; Defer association request handling till SAE auth status is received"); 2675 lim_defer_sme_indication(mac_ctx, session, sub_type, sa, 2676 assoc_req, pmf_connection, 2677 assoc_req_copied, dup_entry, sta_ds, 2678 peer_aid); 2679 2680 return QDF_STATUS_SUCCESS; 2681 } 2682 2683 if (session->opmode == QDF_P2P_GO_MODE) { 2684 /* 2685 * WAR: In P2P GO mode, if the P2P client device 2686 * is only HT capable and not VHT capable, but the P2P 2687 * GO device is VHT capable and advertises 2x2 NSS with 2688 * HT capability client device, which results in IOT 2689 * issues. 2690 * When GO is operating in DBS mode, GO beacons 2691 * advertise 2x2 capability but include OMN IE to 2692 * indicate current operating mode of 1x1. But here 2693 * peer device is only HT capable and will not 2694 * understand OMN IE. 2695 */ 2696 force_1x1 = wlan_p2p_check_oui_and_force_1x1( 2697 frm_body + LIM_ASSOC_REQ_IE_OFFSET, 2698 frame_len - LIM_ASSOC_REQ_IE_OFFSET); 2699 } 2700 2701 /* Send assoc indication to SME */ 2702 if (!lim_send_assoc_ind_to_sme(mac_ctx, session, sub_type, sa, 2703 assoc_req, akm_type, pmf_connection, 2704 &assoc_req_copied, dup_entry, force_1x1, 2705 peer_aid)) 2706 goto error; 2707 2708 return QDF_STATUS_SUCCESS; 2709 2710 error: 2711 lim_process_assoc_cleanup(mac_ctx, session, assoc_req, sta_ds, 2712 assoc_req_copied); 2713 2714 return QDF_STATUS_E_FAILURE; 2715 } 2716 2717 /** 2718 * lim_process_assoc_req_frame() - Process RE/ASSOC Request frame. 2719 * @mac_ctx: Pointer to Global MAC structure 2720 * @rx_pkt_info: A pointer to Buffer descriptor + associated PDUs 2721 * @sub_type: Indicates whether it is Association Request(=0) or Reassociation 2722 * Request(=1) frame 2723 * @session: pe session entry 2724 * 2725 * This function is called to process RE/ASSOC Request frame. 2726 * 2727 * @Return: void 2728 */ lim_process_assoc_req_frame(struct mac_context * mac_ctx,uint8_t * rx_pkt_info,uint8_t sub_type,struct pe_session * session)2729 void lim_process_assoc_req_frame(struct mac_context *mac_ctx, 2730 uint8_t *rx_pkt_info, 2731 uint8_t sub_type, 2732 struct pe_session *session) 2733 { 2734 uint8_t *frm_body; 2735 uint16_t assoc_id = 0; 2736 uint32_t frame_len; 2737 tpSirMacMgmtHdr hdr; 2738 tpDphHashNode sta_ds = NULL; 2739 struct wlan_objmgr_vdev *vdev; 2740 tpSirAssocReq assoc_req; 2741 2742 hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); 2743 frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); 2744 2745 pe_nofl_rl_debug("Assoc req RX: subtype %d vdev %d sys role %d lim state %d rssi %d from " QDF_MAC_ADDR_FMT, 2746 sub_type, session->vdev_id, GET_LIM_SYSTEM_ROLE(session), 2747 session->limMlmState, 2748 WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info), 2749 QDF_MAC_ADDR_REF(hdr->sa)); 2750 2751 if (QDF_IS_STATUS_ERROR(lim_check_assoc_req(mac_ctx, sub_type, 2752 hdr->sa, session))) 2753 return; 2754 2755 vdev = session->vdev; 2756 if (!vdev) { 2757 pe_err("vdev is NULL"); 2758 return; 2759 } 2760 2761 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_UP || 2762 wlan_vdev_mlme_get_substate(vdev) != WLAN_VDEV_SS_UP_ACTIVE) { 2763 pe_err("SAP is not up, drop ASSOC REQ on sessionid: %d", 2764 session->peSessionId); 2765 2766 return; 2767 } 2768 2769 /* 2770 * If a STA is already present in DPH and it is initiating a Assoc 2771 * re-transmit, do not process it. This can happen when first Assoc Req 2772 * frame is received but ACK lost at STA side. The ACK for this dropped 2773 * Assoc Req frame should be sent by HW. Host simply does not process it 2774 * once the entry for the STA is already present in DPH. 2775 */ 2776 sta_ds = dph_lookup_hash_entry(mac_ctx, hdr->sa, &assoc_id, 2777 &session->dph.dphHashTable); 2778 if (sta_ds && !sta_ds->rmfEnabled) { 2779 /* 2780 * Drop only retries for non-PMF assoc requests. 2781 * For PMF case: 2782 * a) Before key installation - Drop assoc request 2783 * b) After key installation - Send SA query 2784 */ 2785 if (hdr->fc.retry > 0) { 2786 pe_err("STA is initiating Assoc Req after ACK lost. Do not process sessionid: %d sys sub_type=%d for role=%d from: " 2787 QDF_MAC_ADDR_FMT, session->peSessionId, 2788 sub_type, GET_LIM_SYSTEM_ROLE(session), 2789 QDF_MAC_ADDR_REF(hdr->sa)); 2790 return; 2791 } else if (sub_type == LIM_REASSOC) { 2792 /* 2793 * SAP should send reassoc response with reject code 2794 * to avoid IOT issues. as per the specification SAP 2795 * should do 4-way handshake after reassoc response and 2796 * some STA doesn't like 4way handshake after reassoc 2797 * where some STA does expect 4-way handshake. 2798 */ 2799 lim_send_assoc_rsp_mgmt_frame( 2800 mac_ctx, STATUS_ASSOC_DENIED_UNSPEC, 2801 sta_ds->assocId, sta_ds->staAddr, 2802 sub_type, sta_ds, session, false); 2803 pe_err("Rejecting reassoc req from STA"); 2804 return; 2805 } else { 2806 /* 2807 * Do this only for non PMF case. 2808 * STA might have missed the assoc response, so it is 2809 * sending assoc request frame again. 2810 */ 2811 lim_send_assoc_rsp_mgmt_frame( 2812 mac_ctx, QDF_STATUS_SUCCESS, 2813 sta_ds->assocId, sta_ds->staAddr, 2814 sub_type, 2815 sta_ds, session, false); 2816 pe_err("DUT already received an assoc request frame and STA is sending another assoc req.So, do not Process sessionid: %d sys sub_type: %d for role: %d from: " 2817 QDF_MAC_ADDR_FMT, 2818 session->peSessionId, sub_type, 2819 session->limSystemRole, 2820 QDF_MAC_ADDR_REF(hdr->sa)); 2821 return; 2822 } 2823 } else if (sta_ds && sta_ds->rmfEnabled && !sta_ds->is_key_installed) { 2824 /* When PMF enabled, SA Query will be triggered 2825 * unexpectedly if duplicated assoc_req received - 2826 * 1) after pre_auth node deleted and 2827 * 2) before key installed. 2828 * Here drop such duplicated assoc_req frame. 2829 */ 2830 pe_err("Drop duplicate assoc_req before 4-way HS"); 2831 return; 2832 } 2833 2834 /* Get pointer to Re/Association Request frame body */ 2835 frm_body = WMA_GET_RX_MPDU_DATA(rx_pkt_info); 2836 2837 if (IEEE80211_IS_MULTICAST(hdr->sa)) { 2838 /* 2839 * Rcvd Re/Assoc Req frame from BC/MC address Log error and 2840 * ignore it 2841 */ 2842 pe_err("Rcvd: %s Req, sessionid: %d from a BC/MC address" 2843 QDF_MAC_ADDR_FMT, 2844 (LIM_ASSOC == sub_type) ? "Assoc" : "ReAssoc", 2845 session->peSessionId, QDF_MAC_ADDR_REF(hdr->sa)); 2846 return; 2847 } 2848 2849 if (false == lim_chk_sa_da(mac_ctx, hdr, session, sub_type)) 2850 return; 2851 2852 /* Allocate memory for the Assoc Request frame */ 2853 assoc_req = qdf_mem_malloc(sizeof(*assoc_req)); 2854 if (!assoc_req) 2855 return; 2856 2857 if (!lim_alloc_assoc_req_frm_buf(assoc_req, 2858 WMA_GET_QDF_NBUF(rx_pkt_info), 2859 WMA_GET_RX_MAC_HEADER_LEN(rx_pkt_info), 2860 frame_len)) 2861 goto error; 2862 2863 lim_proc_assoc_req_frm_cmn(mac_ctx, sub_type, session, hdr->sa, 2864 assoc_req, 0); 2865 2866 if (sub_type == LIM_ASSOC) { 2867 lim_cp_stats_cstats_log_assoc_req_evt 2868 (session, CSTATS_DIR_RX, hdr->bssId, hdr->sa, 2869 assoc_req->ssId.length, assoc_req->ssId.ssId, 2870 assoc_req->HTCaps.present, assoc_req->VHTCaps.present, 2871 assoc_req->he_cap.present, assoc_req->eht_cap.present, 2872 false); 2873 } else if (sub_type == LIM_REASSOC) { 2874 lim_cp_stats_cstats_log_assoc_req_evt 2875 (session, CSTATS_DIR_RX, hdr->bssId, hdr->sa, 2876 assoc_req->ssId.length, assoc_req->ssId.ssId, 2877 assoc_req->HTCaps.present, assoc_req->VHTCaps.present, 2878 assoc_req->he_cap.present, assoc_req->eht_cap.present, 2879 true); 2880 } 2881 2882 return; 2883 error: 2884 if (assoc_req) { 2885 lim_free_assoc_req_frm_buf(assoc_req); 2886 qdf_mem_free(assoc_req); 2887 } 2888 } 2889 2890 #ifdef FEATURE_WLAN_WAPI 2891 /** 2892 * lim_fill_assoc_ind_wapi_info()- Updates WAPI data in assoc indication 2893 * @mac_ctx: Global Mac context 2894 * @assoc_req: pointer to association request 2895 * @assoc_ind: Pointer to association indication 2896 * @wpsie: WPS IE 2897 * 2898 * This function updates WAPI meta data in association indication message 2899 * sent to SME. 2900 * 2901 * Return: None 2902 */ lim_fill_assoc_ind_wapi_info(struct mac_context * mac_ctx,tpSirAssocReq assoc_req,tpLimMlmAssocInd assoc_ind,const uint8_t * wpsie)2903 static void lim_fill_assoc_ind_wapi_info(struct mac_context *mac_ctx, 2904 tpSirAssocReq assoc_req, tpLimMlmAssocInd assoc_ind, 2905 const uint8_t *wpsie) 2906 { 2907 if (assoc_req->wapiPresent && (!wpsie)) { 2908 pe_debug("Received WAPI IE length in Assoc Req is %d", 2909 assoc_req->wapi.length); 2910 assoc_ind->wapiIE.wapiIEdata[0] = WLAN_ELEMID_WAPI; 2911 assoc_ind->wapiIE.wapiIEdata[1] = assoc_req->wapi.length; 2912 qdf_mem_copy(&assoc_ind->wapiIE.wapiIEdata[2], 2913 assoc_req->wapi.info, assoc_req->wapi.length); 2914 assoc_ind->wapiIE.length = 2915 2 + assoc_req->wapi.length; 2916 } 2917 return; 2918 } 2919 #else lim_fill_assoc_ind_wapi_info(struct mac_context * mac_ctx,tpSirAssocReq assoc_req,tpLimMlmAssocInd assoc_ind,const uint8_t * wpsie)2920 static void lim_fill_assoc_ind_wapi_info( 2921 struct mac_context *mac_ctx, 2922 tpSirAssocReq assoc_req, tpLimMlmAssocInd assoc_ind, 2923 const uint8_t *wpsie) 2924 { 2925 } 2926 #endif 2927 2928 #ifdef WLAN_FEATURE_11AX lim_fill_assoc_he_info(struct mac_context * mac_ctx,struct pe_session * session_entry,tpSirAssocReq assoc_req,tpLimMlmAssocInd assoc_ind)2929 static bool lim_fill_assoc_he_info(struct mac_context *mac_ctx, 2930 struct pe_session *session_entry, 2931 tpSirAssocReq assoc_req, 2932 tpLimMlmAssocInd assoc_ind) 2933 { 2934 if (session_entry->he_capable && assoc_req->he_cap.present) { 2935 if (session_entry->limRFBand == REG_BAND_2G) { 2936 if (session_entry->ch_width == CH_WIDTH_20MHZ) 2937 assoc_ind->chan_info.info = MODE_11AX_HE20; 2938 else if (session_entry->ch_width == CH_WIDTH_40MHZ && 2939 assoc_req->he_cap.chan_width_0 == 1) 2940 assoc_ind->chan_info.info = MODE_11AX_HE40; 2941 else 2942 assoc_ind->chan_info.info = MODE_11AX_HE20; 2943 } else { 2944 if (session_entry->ch_width == CH_WIDTH_160MHZ && 2945 assoc_req->he_cap.chan_width_2 == 1) 2946 assoc_ind->chan_info.info = MODE_11AX_HE160; 2947 else if (session_entry->ch_width >= CH_WIDTH_80MHZ && 2948 assoc_req->he_cap.chan_width_1 == 1) 2949 assoc_ind->chan_info.info = MODE_11AX_HE80; 2950 else if (session_entry->ch_width >= CH_WIDTH_40MHZ && 2951 assoc_req->he_cap.chan_width_1 == 1) 2952 assoc_ind->chan_info.info = MODE_11AX_HE40; 2953 else 2954 assoc_ind->chan_info.info = MODE_11AX_HE20; 2955 } 2956 return true; 2957 } 2958 2959 return false; 2960 } 2961 #else lim_fill_assoc_he_info(struct mac_context * mac_ctx,struct pe_session * session_entry,tpSirAssocReq assoc_req,tpLimMlmAssocInd assoc_ind)2962 static bool lim_fill_assoc_he_info(struct mac_context *mac_ctx, 2963 struct pe_session *session_entry, 2964 tpSirAssocReq assoc_req, 2965 tpLimMlmAssocInd assoc_ind) 2966 { 2967 return false; 2968 } 2969 #endif 2970 /** 2971 * lim_fill_assoc_ind_info() - Updates HE/VHT/HT information in assoc indication 2972 * @mac_ctx: Global Mac context 2973 * @assoc_req: pointer to association request 2974 * @session_entry: PE session entry 2975 * @assoc_ind: Pointer to association indication 2976 * 2977 * This function updates VHT information in association indication message 2978 * sent to SME. 2979 * 2980 * Return: None 2981 */ lim_fill_assoc_ind_info(struct mac_context * mac_ctx,struct pe_session * session_entry,tpSirAssocReq assoc_req,tpLimMlmAssocInd assoc_ind,tpDphHashNode sta_ds)2982 static void lim_fill_assoc_ind_info(struct mac_context *mac_ctx, 2983 struct pe_session *session_entry, 2984 tpSirAssocReq assoc_req, 2985 tpLimMlmAssocInd assoc_ind, 2986 tpDphHashNode sta_ds) 2987 { 2988 uint8_t chan; 2989 uint8_t i; 2990 bool nw_type_11b = true; 2991 uint32_t cfreq = 0; 2992 enum reg_wifi_band band; 2993 2994 band = wlan_reg_freq_to_band(session_entry->curr_op_freq); 2995 cfreq = wlan_reg_chan_band_to_freq(mac_ctx->pdev, 2996 session_entry->ch_center_freq_seg0, BIT(band)); 2997 assoc_ind->chan_info.band_center_freq1 = cfreq; 2998 if (session_entry->ch_center_freq_seg1) { 2999 cfreq = wlan_reg_chan_band_to_freq(mac_ctx->pdev, 3000 session_entry->ch_center_freq_seg1, BIT(band)); 3001 assoc_ind->chan_info.band_center_freq2 = cfreq; 3002 } 3003 if (session_entry->ch_width == CH_WIDTH_40MHZ) { 3004 if (session_entry->htSecondaryChannelOffset == 3005 PHY_DOUBLE_CHANNEL_LOW_PRIMARY) 3006 assoc_ind->chan_info.band_center_freq1 += 10; 3007 else 3008 assoc_ind->chan_info.band_center_freq1 -= 10; 3009 } 3010 if (lim_fill_assoc_he_info(mac_ctx, session_entry, 3011 assoc_req, assoc_ind)) 3012 return; 3013 3014 if (session_entry->limRFBand == REG_BAND_2G) { 3015 if (session_entry->vhtCapability 3016 && assoc_req->VHTCaps.present) { 3017 assoc_ind->chan_info.info = MODE_11AC_VHT20_2G; 3018 } else if (session_entry->htCapability 3019 && assoc_req->HTCaps.present) { 3020 assoc_ind->chan_info.info = MODE_11NG_HT20; 3021 } else { 3022 for (i = 0; i < SIR_NUM_11A_RATES; i++) { 3023 if (sirIsArate(sta_ds-> 3024 supportedRates.llaRates[i] 3025 & 0x7F)) { 3026 assoc_ind->chan_info.info = MODE_11G; 3027 nw_type_11b = false; 3028 break; 3029 } 3030 } 3031 if (nw_type_11b) 3032 assoc_ind->chan_info.info = MODE_11B; 3033 } 3034 return; 3035 } 3036 3037 if (session_entry->vhtCapability && assoc_req->VHTCaps.present) { 3038 if ((session_entry->ch_width > CH_WIDTH_40MHZ) 3039 && assoc_req->HTCaps.supportedChannelWidthSet) { 3040 chan = session_entry->ch_center_freq_seg0; 3041 assoc_ind->chan_info.band_center_freq1 = 3042 cds_chan_to_freq(chan); 3043 assoc_ind->chan_info.info = MODE_11AC_VHT80; 3044 return; 3045 } 3046 3047 if ((session_entry->ch_width == CH_WIDTH_40MHZ) 3048 && assoc_req->HTCaps.supportedChannelWidthSet) { 3049 assoc_ind->chan_info.info = MODE_11AC_VHT40; 3050 return; 3051 } 3052 3053 assoc_ind->chan_info.info = MODE_11AC_VHT20; 3054 return; 3055 } 3056 3057 if (session_entry->htCapability && assoc_req->HTCaps.present) { 3058 if ((session_entry->ch_width == CH_WIDTH_40MHZ) 3059 && assoc_req->HTCaps.supportedChannelWidthSet) { 3060 assoc_ind->chan_info.info = MODE_11NA_HT40; 3061 return; 3062 } 3063 3064 assoc_ind->chan_info.info = MODE_11NA_HT20; 3065 return; 3066 } 3067 3068 assoc_ind->chan_info.info = MODE_11A; 3069 return; 3070 } 3071 fill_mlm_assoc_ind_vht(tpSirAssocReq assocreq,tpDphHashNode stads,tpLimMlmAssocInd assocind)3072 static void fill_mlm_assoc_ind_vht(tpSirAssocReq assocreq, 3073 tpDphHashNode stads, 3074 tpLimMlmAssocInd assocind) 3075 { 3076 if (stads->mlmStaContext.vhtCapability) { 3077 /* ampdu */ 3078 assocind->ampdu = true; 3079 3080 /* sgi */ 3081 if (assocreq->VHTCaps.shortGI80MHz || 3082 assocreq->VHTCaps.shortGI160and80plus80MHz) 3083 assocind->sgi_enable = true; 3084 3085 /* stbc */ 3086 assocind->tx_stbc = assocreq->VHTCaps.txSTBC; 3087 assocind->rx_stbc = assocreq->VHTCaps.rxSTBC; 3088 3089 /* ch width */ 3090 assocind->ch_width = stads->vhtSupportedChannelWidthSet ? 3091 eHT_CHANNEL_WIDTH_80MHZ : 3092 stads->htSupportedChannelWidthSet ? 3093 eHT_CHANNEL_WIDTH_40MHZ : eHT_CHANNEL_WIDTH_20MHZ; 3094 3095 /* mode */ 3096 assocind->mode = SIR_SME_PHY_MODE_VHT; 3097 assocind->rx_mcs_map = assocreq->VHTCaps.rxMCSMap & 0xff; 3098 assocind->tx_mcs_map = assocreq->VHTCaps.txMCSMap & 0xff; 3099 } 3100 } 3101 3102 /** 3103 *lim_convert_channel_width_enum() - map between two channel width enums 3104 *@ch_width: channel width of enum type phy_ch_width 3105 * 3106 *Return: channel width of enum type tSirMacHTChannelWidth 3107 */ 3108 static tSirMacHTChannelWidth lim_convert_channel_width_enum(enum phy_ch_width ch_width)3109 lim_convert_channel_width_enum(enum phy_ch_width ch_width) 3110 { 3111 switch (ch_width) { 3112 case CH_WIDTH_20MHZ: 3113 return eHT_CHANNEL_WIDTH_20MHZ; 3114 case CH_WIDTH_40MHZ: 3115 return eHT_CHANNEL_WIDTH_40MHZ; 3116 case CH_WIDTH_80MHZ: 3117 return eHT_CHANNEL_WIDTH_80MHZ; 3118 case CH_WIDTH_160MHZ: 3119 return eHT_CHANNEL_WIDTH_160MHZ; 3120 case CH_WIDTH_80P80MHZ: 3121 return eHT_CHANNEL_WIDTH_80P80MHZ; 3122 case CH_WIDTH_320MHZ: 3123 return eHT_CHANNEL_WIDTH_320MHZ; 3124 case CH_WIDTH_MAX: 3125 return eHT_MAX_CHANNEL_WIDTH; 3126 case CH_WIDTH_5MHZ: 3127 break; 3128 case CH_WIDTH_10MHZ: 3129 break; 3130 case CH_WIDTH_INVALID: 3131 break; 3132 } 3133 pe_debug("invalid enum: %d", ch_width); 3134 return eHT_CHANNEL_WIDTH_20MHZ; 3135 } 3136 3137 /** 3138 * lim_convert_rate_flags_enum() - map between channel width and rate flag enums 3139 * @rate_flags: the current rate flags 3140 * @ch_width: channel width of enum type phy_ch_width 3141 * 3142 * Return: updated rate flags per ch width 3143 */ lim_convert_rate_flags_enum(uint32_t rate_flags,enum phy_ch_width ch_width)3144 static uint32_t lim_convert_rate_flags_enum(uint32_t rate_flags, 3145 enum phy_ch_width ch_width) 3146 { 3147 if (rate_flags & (TX_RATE_HE160 | 3148 TX_RATE_HE80 | 3149 TX_RATE_HE40 | 3150 TX_RATE_HE20)) { 3151 switch (ch_width) { 3152 case CH_WIDTH_20MHZ: 3153 rate_flags |= TX_RATE_HE20; 3154 break; 3155 case CH_WIDTH_40MHZ: 3156 rate_flags |= TX_RATE_HE40; 3157 break; 3158 case CH_WIDTH_80MHZ: 3159 rate_flags |= TX_RATE_HE80; 3160 break; 3161 case CH_WIDTH_160MHZ: 3162 case CH_WIDTH_80P80MHZ: 3163 rate_flags |= TX_RATE_HE160; 3164 break; 3165 default: 3166 break; 3167 } 3168 } else if (rate_flags & (TX_RATE_VHT160 | 3169 TX_RATE_VHT80 | 3170 TX_RATE_VHT40 | 3171 TX_RATE_VHT20)) { 3172 switch (ch_width) { 3173 case CH_WIDTH_20MHZ: 3174 rate_flags |= TX_RATE_VHT20; 3175 break; 3176 case CH_WIDTH_40MHZ: 3177 rate_flags |= TX_RATE_VHT40; 3178 break; 3179 case CH_WIDTH_80MHZ: 3180 rate_flags |= TX_RATE_VHT80; 3181 break; 3182 case CH_WIDTH_160MHZ: 3183 case CH_WIDTH_80P80MHZ: 3184 rate_flags |= TX_RATE_VHT160; 3185 break; 3186 default: 3187 break; 3188 } 3189 } else { 3190 switch (ch_width) { 3191 case CH_WIDTH_20MHZ: 3192 rate_flags |= TX_RATE_HT20; 3193 break; 3194 case CH_WIDTH_40MHZ: 3195 rate_flags |= TX_RATE_HT40; 3196 break; 3197 default: 3198 break; 3199 } 3200 } 3201 return rate_flags; 3202 } 3203 lim_fill_assoc_ind_he_bw_info(tpLimMlmAssocInd assoc_ind,tpDphHashNode sta_ds,struct pe_session * session_entry)3204 static void lim_fill_assoc_ind_he_bw_info(tpLimMlmAssocInd assoc_ind, 3205 tpDphHashNode sta_ds, 3206 struct pe_session *session_entry) 3207 { 3208 if (lim_is_sta_he_capable(sta_ds) && 3209 lim_is_session_he_capable(session_entry)) { 3210 assoc_ind->ch_width = 3211 lim_convert_channel_width_enum(sta_ds->ch_width); 3212 assoc_ind->chan_info.rate_flags = 3213 lim_convert_rate_flags_enum(assoc_ind->chan_info.rate_flags, 3214 sta_ds->ch_width); 3215 } 3216 } 3217 3218 /** 3219 * lim_fill_assoc_ind_real_max_mcs_idx() - fill max real mcs index to assoc ind 3220 * @assoc_ind: assoc_ind to fill 3221 * @assoc_req: pointer to tpSirAssocReq 3222 * @sta_ds: pointer to tpDphHashNode 3223 * @session: pointer to session 3224 * 3225 * Return: void 3226 */ lim_fill_assoc_ind_real_max_mcs_idx(tpLimMlmAssocInd assoc_ind,tpSirAssocReq assoc_req,tpDphHashNode sta_ds,struct pe_session * session)3227 static void lim_fill_assoc_ind_real_max_mcs_idx(tpLimMlmAssocInd assoc_ind, 3228 tpSirAssocReq assoc_req, 3229 tpDphHashNode sta_ds, 3230 struct pe_session *session) 3231 { 3232 assoc_ind->max_real_mcs_idx = INVALID_MCS_NSS_INDEX; 3233 3234 if (lim_is_sta_he_capable(sta_ds) && 3235 lim_is_session_he_capable(session)) 3236 assoc_ind->max_real_mcs_idx = lim_get_he_max_mcs_idx( 3237 sta_ds->ch_width, &assoc_req->he_cap); 3238 3239 if (assoc_ind->max_real_mcs_idx == INVALID_MCS_NSS_INDEX && 3240 sta_ds->mlmStaContext.vhtCapability) 3241 assoc_ind->max_real_mcs_idx = 3242 lim_get_vht_max_mcs_idx(&assoc_req->VHTCaps); 3243 3244 if (assoc_ind->max_real_mcs_idx == INVALID_MCS_NSS_INDEX) 3245 assoc_ind->max_real_mcs_idx = assoc_ind->max_mcs_idx; 3246 3247 if (assoc_ind->max_real_mcs_idx == INVALID_MCS_NSS_INDEX) 3248 assoc_ind->max_real_mcs_idx = assoc_ind->max_ext_idx; 3249 3250 if (assoc_ind->max_real_mcs_idx == INVALID_MCS_NSS_INDEX) 3251 assoc_ind->max_real_mcs_idx = assoc_ind->max_supp_idx; 3252 } 3253 3254 #ifdef WLAN_FEATURE_11BE_MLO 3255 static void lim_fill_lim_assoc_ind_mac_addr_copy(tpLimMlmAssocInd assoc_ind,tpDphHashNode sta_ds,uint32_t num_bytes)3256 lim_fill_lim_assoc_ind_mac_addr_copy(tpLimMlmAssocInd assoc_ind, 3257 tpDphHashNode sta_ds, 3258 uint32_t num_bytes) 3259 { 3260 qdf_mem_copy((uint8_t *)assoc_ind->peer_mld_addr, 3261 (uint8_t *)sta_ds->mld_addr, 3262 num_bytes); 3263 } 3264 #else /* WLAN_FEATURE_11BE_MLO */ 3265 static inline void lim_fill_lim_assoc_ind_mac_addr_copy(tpLimMlmAssocInd assoc_ind,tpDphHashNode sta_ds,uint32_t num_bytes)3266 lim_fill_lim_assoc_ind_mac_addr_copy(tpLimMlmAssocInd assoc_ind, 3267 tpDphHashNode sta_ds, 3268 uint32_t num_bytes) 3269 { 3270 } 3271 #endif /* WLAN_FEATURE_11BE_MLO */ 3272 lim_fill_lim_assoc_ind_params(tpLimMlmAssocInd assoc_ind,struct mac_context * mac_ctx,tpDphHashNode sta_ds,struct pe_session * session_entry)3273 bool lim_fill_lim_assoc_ind_params( 3274 tpLimMlmAssocInd assoc_ind, 3275 struct mac_context *mac_ctx, 3276 tpDphHashNode sta_ds, 3277 struct pe_session *session_entry) 3278 { 3279 tpSirAssocReq assoc_req; 3280 uint16_t rsn_len; 3281 uint32_t phy_mode; 3282 const uint8_t *wpsie = NULL; 3283 bool wme_enable; 3284 struct wlan_objmgr_vdev *vdev; 3285 struct vdev_mlme_obj *mlme_obj; 3286 uint8_t country_iso[REG_ALPHA2_LEN + 1]; 3287 tDot11fIESuppOperatingClasses *oper_class; 3288 3289 if (!session_entry->parsedAssocReq) { 3290 pe_err(" Parsed Assoc req is NULL"); 3291 return false; 3292 } 3293 3294 /* Get a copy of the already parsed Assoc Request */ 3295 assoc_req = 3296 (tpSirAssocReq)session_entry->parsedAssocReq[sta_ds->assocId]; 3297 3298 if (!assoc_req) { 3299 pe_err("assoc req for assoc_id:%d is NULL", sta_ds->assocId); 3300 return false; 3301 } 3302 3303 /* Get the phy_mode */ 3304 lim_get_phy_mode(mac_ctx, &phy_mode, session_entry); 3305 3306 qdf_mem_copy((uint8_t *)assoc_ind->peerMacAddr, 3307 (uint8_t *)sta_ds->staAddr, sizeof(tSirMacAddr)); 3308 lim_fill_lim_assoc_ind_mac_addr_copy(assoc_ind, sta_ds, 3309 sizeof(tSirMacAddr)); 3310 assoc_ind->aid = sta_ds->assocId; 3311 qdf_mem_copy((uint8_t *)&assoc_ind->ssId, 3312 (uint8_t *)&assoc_req->ssId, 3313 assoc_req->ssId.length + 1); 3314 assoc_ind->sessionId = session_entry->peSessionId; 3315 assoc_ind->authType = sta_ds->mlmStaContext.authType; 3316 assoc_ind->akm_type = sta_ds->mlmStaContext.akm_type; 3317 assoc_ind->capabilityInfo = assoc_req->capabilityInfo; 3318 3319 /* Fill in RSN IE information */ 3320 assoc_ind->rsnIE.length = 0; 3321 /* if WPS IE is present, ignore RSN IE */ 3322 if (assoc_req->addIEPresent && assoc_req->addIE.length) { 3323 wpsie = limGetWscIEPtr( 3324 mac_ctx, 3325 assoc_req->addIE.addIEdata, 3326 assoc_req->addIE.length); 3327 } 3328 if (assoc_req->rsnPresent && !wpsie) { 3329 pe_debug("Assoc Req RSN IE len: %d", 3330 assoc_req->rsn.length); 3331 assoc_ind->rsnIE.length = 2 + assoc_req->rsn.length; 3332 assoc_ind->rsnIE.rsnIEdata[0] = WLAN_ELEMID_RSN; 3333 assoc_ind->rsnIE.rsnIEdata[1] = 3334 assoc_req->rsn.length; 3335 qdf_mem_copy( 3336 &assoc_ind->rsnIE.rsnIEdata[2], 3337 assoc_req->rsn.info, 3338 assoc_req->rsn.length); 3339 } 3340 /* Fill in 802.11h related info */ 3341 if (assoc_req->powerCapabilityPresent && 3342 assoc_req->supportedChannelsPresent) { 3343 assoc_ind->spectrumMgtIndicator = true; 3344 assoc_ind->powerCap.minTxPower = 3345 assoc_req->powerCapability.minTxPower; 3346 assoc_ind->powerCap.maxTxPower = 3347 assoc_req->powerCapability.maxTxPower; 3348 lim_convert_supported_channels( 3349 mac_ctx, assoc_ind, 3350 assoc_req); 3351 } else { 3352 assoc_ind->spectrumMgtIndicator = false; 3353 } 3354 3355 /* This check is to avoid extra Sec IEs present incase of WPS */ 3356 if (assoc_req->wpaPresent && !wpsie) { 3357 rsn_len = assoc_ind->rsnIE.length; 3358 if ((rsn_len + assoc_req->wpa.length) 3359 >= WLAN_MAX_IE_LEN) { 3360 pe_err("rsnIEdata index out of bounds: %d", 3361 rsn_len); 3362 return false; 3363 } 3364 assoc_ind->rsnIE.rsnIEdata[rsn_len] = 3365 SIR_MAC_WPA_EID; 3366 assoc_ind->rsnIE.rsnIEdata[rsn_len + 1] 3367 = assoc_req->wpa.length; 3368 qdf_mem_copy( 3369 &assoc_ind->rsnIE.rsnIEdata[rsn_len + 2], 3370 assoc_req->wpa.info, assoc_req->wpa.length); 3371 assoc_ind->rsnIE.length += 2 + assoc_req->wpa.length; 3372 } 3373 lim_fill_assoc_ind_wapi_info(mac_ctx, assoc_req, assoc_ind, wpsie); 3374 3375 assoc_ind->addIE.length = 0; 3376 if (assoc_req->addIEPresent) { 3377 qdf_mem_copy( 3378 &assoc_ind->addIE.addIEdata, 3379 assoc_req->addIE.addIEdata, 3380 assoc_req->addIE.length); 3381 assoc_ind->addIE.length = assoc_req->addIE.length; 3382 } 3383 /* 3384 * Add HT Capabilities into addIE for OBSS 3385 * processing in hostapd 3386 */ 3387 if (assoc_req->HTCaps.present) { 3388 qdf_mem_copy(&assoc_ind->ht_caps, &assoc_req->HTCaps, 3389 sizeof(tDot11fIEHTCaps)); 3390 rsn_len = assoc_ind->addIE.length; 3391 if (assoc_ind->addIE.length + DOT11F_IE_HTCAPS_MIN_LEN 3392 + 2 < WLAN_MAX_IE_LEN) { 3393 assoc_ind->addIE.addIEdata[rsn_len] = 3394 WLAN_ELEMID_HTCAP_ANA; 3395 assoc_ind->addIE.addIEdata[rsn_len + 1] = 3396 DOT11F_IE_HTCAPS_MIN_LEN; 3397 qdf_mem_copy( 3398 &assoc_ind->addIE.addIEdata[rsn_len + 2], 3399 ((uint8_t *)&assoc_req->HTCaps) + 1, 3400 DOT11F_IE_HTCAPS_MIN_LEN); 3401 assoc_ind->addIE.length += 3402 2 + DOT11F_IE_HTCAPS_MIN_LEN; 3403 } else { 3404 pe_err("Fail:HT capabilities IE to addIE"); 3405 } 3406 } 3407 3408 if (assoc_req->wmeInfoPresent) { 3409 /* Set whether AP is enabled with WMM or not */ 3410 wme_enable = mac_ctx->mlme_cfg->wmm_params.wme_enabled; 3411 assoc_ind->WmmStaInfoPresent = wme_enable; 3412 /* 3413 * Note: we are not rejecting association here 3414 * because IOT will fail 3415 */ 3416 } 3417 /* Required for indicating the frames to upper layer */ 3418 assoc_ind->assocReqLength = assoc_req->assocReqFrameLength; 3419 assoc_ind->assocReqPtr = assoc_req->assocReqFrame; 3420 3421 assoc_ind->chan_info.mhz = session_entry->curr_op_freq; 3422 assoc_ind->chan_info.band_center_freq1 = 3423 session_entry->curr_op_freq; 3424 assoc_ind->chan_info.band_center_freq2 = 0; 3425 assoc_ind->chan_info.reg_info_1 = 3426 (session_entry->maxTxPower << 16); 3427 assoc_ind->chan_info.reg_info_2 = 3428 (session_entry->maxTxPower << 8); 3429 assoc_ind->chan_info.nss = sta_ds->nss; 3430 assoc_ind->chan_info.rate_flags = 3431 lim_get_max_rate_flags(mac_ctx, sta_ds); 3432 assoc_ind->ampdu = false; 3433 assoc_ind->sgi_enable = false; 3434 assoc_ind->tx_stbc = false; 3435 assoc_ind->rx_stbc = false; 3436 assoc_ind->ch_width = eHT_CHANNEL_WIDTH_20MHZ; 3437 assoc_ind->mode = SIR_SME_PHY_MODE_LEGACY; 3438 assoc_ind->max_supp_idx = INVALID_MCS_NSS_INDEX; 3439 assoc_ind->max_ext_idx = INVALID_MCS_NSS_INDEX; 3440 assoc_ind->max_mcs_idx = INVALID_MCS_NSS_INDEX; 3441 assoc_ind->rx_mcs_map = 0xff; 3442 assoc_ind->tx_mcs_map = 0xff; 3443 3444 if (assoc_req->supportedRates.numRates) 3445 assoc_ind->max_supp_idx = 3446 lim_get_max_rate_idx(&assoc_req->supportedRates); 3447 if (assoc_req->extendedRates.numRates) 3448 assoc_ind->max_ext_idx = 3449 lim_get_max_rate_idx(&assoc_req->extendedRates); 3450 3451 if (sta_ds->mlmStaContext.htCapability) { 3452 /* ampdu */ 3453 assoc_ind->ampdu = true; 3454 3455 /* sgi */ 3456 if (sta_ds->htShortGI20Mhz || sta_ds->htShortGI40Mhz) 3457 assoc_ind->sgi_enable = true; 3458 3459 /* stbc */ 3460 assoc_ind->tx_stbc = assoc_req->HTCaps.txSTBC; 3461 assoc_ind->rx_stbc = assoc_req->HTCaps.rxSTBC; 3462 3463 /* ch width */ 3464 assoc_ind->ch_width = 3465 sta_ds->htSupportedChannelWidthSet ? 3466 eHT_CHANNEL_WIDTH_40MHZ : 3467 eHT_CHANNEL_WIDTH_20MHZ; 3468 /* mode */ 3469 assoc_ind->mode = SIR_SME_PHY_MODE_HT; 3470 assoc_ind->max_mcs_idx = lim_get_ht_max_mcs_idx( 3471 &assoc_req->HTCaps); 3472 } 3473 fill_mlm_assoc_ind_vht(assoc_req, sta_ds, assoc_ind); 3474 if (assoc_req->ExtCap.present) { 3475 assoc_ind->ecsa_capable = 3476 ((struct s_ext_cap *)assoc_req->ExtCap.bytes)->ext_chan_switch; 3477 if (assoc_req->ExtCap.num_bytes >= sizeof(assoc_ind->ext_cap)) 3478 qdf_mem_copy(&assoc_ind->ext_cap, 3479 assoc_req->ExtCap.bytes, 3480 sizeof(assoc_ind->ext_cap)); 3481 else 3482 qdf_mem_copy(&assoc_ind->ext_cap, 3483 assoc_req->ExtCap.bytes, 3484 assoc_req->ExtCap.num_bytes); 3485 } 3486 3487 if (assoc_req->supp_operating_classes.present) { 3488 oper_class = &assoc_req->supp_operating_classes; 3489 qdf_mem_zero(country_iso, sizeof(country_iso)); 3490 country_iso[2] = OP_CLASS_GLOBAL; 3491 assoc_ind->supported_band = 3492 wlan_reg_get_band_cap_from_op_class( 3493 country_iso, 3494 oper_class->num_classes, 3495 oper_class->classes); 3496 } 3497 3498 /* updates VHT information in assoc indication */ 3499 if (assoc_req->VHTCaps.present) 3500 qdf_mem_copy(&assoc_ind->vht_caps, &assoc_req->VHTCaps, 3501 sizeof(tDot11fIEVHTCaps)); 3502 else if (assoc_req->vendor_vht_ie.VHTCaps.present) 3503 qdf_mem_copy(&assoc_ind->vht_caps, 3504 &assoc_req->vendor_vht_ie.VHTCaps, 3505 sizeof(tDot11fIEVHTCaps)); 3506 3507 lim_fill_assoc_ind_info(mac_ctx, session_entry, assoc_req, 3508 assoc_ind, sta_ds); 3509 pe_debug("ch_width: %d vht_cap %d ht_cap %d chan_info %d center_freq1 %d", 3510 session_entry->ch_width, 3511 session_entry->vhtCapability, session_entry->htCapability, 3512 assoc_ind->chan_info.info, 3513 assoc_ind->chan_info.band_center_freq1); 3514 assoc_ind->he_caps_present = assoc_req->he_cap.present; 3515 assoc_ind->eht_caps_present = assoc_req->eht_cap.present; 3516 assoc_ind->is_sae_authenticated = 3517 assoc_req->is_sae_authenticated; 3518 /* updates HE bandwidth in assoc indication */ 3519 lim_fill_assoc_ind_he_bw_info(assoc_ind, sta_ds, session_entry); 3520 lim_fill_assoc_ind_real_max_mcs_idx(assoc_ind, assoc_req, 3521 sta_ds, session_entry); 3522 3523 vdev = session_entry->vdev; 3524 if (!vdev) 3525 return true; 3526 3527 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev); 3528 if (!mlme_obj) 3529 pe_err("vdev component object is NULL"); 3530 else 3531 qdf_mem_copy( 3532 &mlme_obj->ext_vdev_ptr->connect_info.chan_info, 3533 &assoc_ind->chan_info, 3534 sizeof(mlme_obj->ext_vdev_ptr->connect_info.chan_info)); 3535 3536 return true; 3537 } 3538 lim_send_mlm_assoc_ind(struct mac_context * mac_ctx,tpDphHashNode sta_ds,struct pe_session * session_entry)3539 QDF_STATUS lim_send_mlm_assoc_ind(struct mac_context *mac_ctx, 3540 tpDphHashNode sta_ds, 3541 struct pe_session *session_entry) 3542 { 3543 tpLimMlmAssocInd assoc_ind; 3544 tpSirAssocReq assoc_req; 3545 uint16_t temp; 3546 uint32_t phy_mode; 3547 uint8_t sub_type; 3548 3549 if (!session_entry->parsedAssocReq) { 3550 pe_err(" Parsed Assoc req is NULL"); 3551 return QDF_STATUS_E_INVAL; 3552 } 3553 3554 /* Get a copy of the already parsed Assoc Request */ 3555 assoc_req = 3556 (tpSirAssocReq) session_entry->parsedAssocReq[sta_ds->assocId]; 3557 3558 if (!assoc_req) { 3559 pe_err("assoc req for assoc_id:%d is NULL", sta_ds->assocId); 3560 return QDF_STATUS_E_INVAL; 3561 } 3562 3563 /* Get the phy_mode */ 3564 lim_get_phy_mode(mac_ctx, &phy_mode, session_entry); 3565 3566 /* Determine if its Assoc or ReAssoc Request */ 3567 if (assoc_req->reassocRequest == 1) 3568 sub_type = LIM_REASSOC; 3569 else 3570 sub_type = LIM_ASSOC; 3571 3572 pe_debug("Sessionid: %d ssid: " QDF_SSID_FMT " sub_type: %d Associd: %d staAddr: " 3573 QDF_MAC_ADDR_FMT, session_entry->peSessionId, 3574 QDF_SSID_REF(assoc_req->ssId.length, assoc_req->ssId.ssId), 3575 sub_type, sta_ds->assocId, 3576 QDF_MAC_ADDR_REF(sta_ds->staAddr)); 3577 3578 wlan_son_ind_assoc_req_frm(session_entry->vdev, sta_ds->staAddr, 3579 assoc_req->reassocRequest, 3580 qdf_nbuf_data(assoc_req->assoc_req_buf), 3581 qdf_nbuf_len(assoc_req->assoc_req_buf), 3582 QDF_STATUS_SUCCESS); 3583 3584 if (sub_type == LIM_ASSOC || sub_type == LIM_REASSOC) { 3585 temp = sizeof(tLimMlmAssocInd); 3586 3587 assoc_ind = qdf_mem_malloc(temp); 3588 if (!assoc_ind) { 3589 if (lim_is_mlo_conn(session_entry, sta_ds)) 3590 lim_release_mlo_conn_idx(mac_ctx, 3591 sta_ds->assocId, 3592 session_entry, false); 3593 else 3594 lim_release_peer_idx(mac_ctx, sta_ds->assocId, 3595 session_entry); 3596 return QDF_STATUS_E_INVAL; 3597 } 3598 if (!lim_fill_lim_assoc_ind_params(assoc_ind, mac_ctx, 3599 sta_ds, session_entry)) { 3600 qdf_mem_free(assoc_ind); 3601 return QDF_STATUS_E_INVAL; 3602 } 3603 3604 pe_debug("assoc_ind->akm_type:%d ", assoc_ind->akm_type); 3605 if (assoc_ind->akm_type == ANI_AKM_TYPE_FT_RSN_PSK) { 3606 lim_send_sme_mgmt_frame_ind(mac_ctx, sub_type, 3607 qdf_nbuf_data(assoc_req->assoc_req_buf), 3608 qdf_nbuf_len(assoc_req->assoc_req_buf), 3609 session_entry->smeSessionId, 3610 0, 0, RXMGMT_FLAG_NONE); 3611 } 3612 lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_IND, 3613 (uint32_t *)assoc_ind); 3614 qdf_mem_free(assoc_ind); 3615 } 3616 3617 return QDF_STATUS_SUCCESS; 3618 } 3619