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