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