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