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