1 /*
2 * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2023 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_ft_preauth.c
22 *
23 * Pre-Authentication implementation for host based roaming
24 */
25 #include <lim_send_messages.h>
26 #include <lim_types.h>
27 #include <lim_ft.h>
28 #include <lim_ft_defs.h>
29 #include <lim_utils.h>
30 #include <lim_prop_exts_utils.h>
31 #include <lim_assoc_utils.h>
32 #include <lim_session.h>
33 #include <lim_session_utils.h>
34 #include <lim_admit_control.h>
35 #include <wlan_scan_api.h>
36 #include "wma.h"
37 #include "wlan_crypto_global_api.h"
38
39 /**
40 * lim_ft_cleanup_pre_auth_info() - Cleanup preauth related information
41 * @mac: Global MAC Context
42 * @pe_session: PE Session
43 *
44 * This routine is called to free the FT context, session and other
45 * information used during preauth operation.
46 *
47 * Return: None
48 */
lim_ft_cleanup_pre_auth_info(struct mac_context * mac,struct pe_session * pe_session)49 void lim_ft_cleanup_pre_auth_info(struct mac_context *mac,
50 struct pe_session *pe_session)
51 {
52 struct pe_session *pReAssocSessionEntry = NULL;
53 uint8_t sessionId = 0;
54
55 if (!pe_session) {
56 pe_err("pe_session is NULL");
57 return;
58 }
59
60 /* Nothing to be done if the session is not in STA mode */
61 if (!LIM_IS_STA_ROLE(pe_session)) {
62 pe_err("pe_session is not in STA mode");
63 return;
64 }
65
66 if (pe_session->ftPEContext.pFTPreAuthReq) {
67 pReAssocSessionEntry =
68 pe_find_session_by_bssid(mac,
69 pe_session->ftPEContext.
70 pFTPreAuthReq->preAuthbssId,
71 &sessionId);
72
73 if (pe_session->ftPEContext.pFTPreAuthReq->
74 pbssDescription) {
75 qdf_mem_free(pe_session->ftPEContext.pFTPreAuthReq->
76 pbssDescription);
77 pe_session->ftPEContext.pFTPreAuthReq->
78 pbssDescription = NULL;
79 }
80 qdf_mem_free(pe_session->ftPEContext.pFTPreAuthReq);
81 pe_session->ftPEContext.pFTPreAuthReq = NULL;
82 }
83
84 if (pe_session->ftPEContext.pAddBssReq) {
85 qdf_mem_free(pe_session->ftPEContext.pAddBssReq);
86 pe_session->ftPEContext.pAddBssReq = NULL;
87 }
88
89 if (pe_session->ftPEContext.pAddStaReq) {
90 qdf_mem_free(pe_session->ftPEContext.pAddStaReq);
91 pe_session->ftPEContext.pAddStaReq = NULL;
92 }
93
94 /* The session is being deleted, cleanup the contents */
95 qdf_mem_zero(&pe_session->ftPEContext, sizeof(tftPEContext));
96
97 /* Delete the session created while handling pre-auth response */
98 if (pReAssocSessionEntry) {
99 /* If we have successful pre-auth response, then we would have
100 * created a session on which reassoc request will be sent
101 */
102 if (pReAssocSessionEntry->valid &&
103 pReAssocSessionEntry->limSmeState ==
104 eLIM_SME_WT_REASSOC_STATE) {
105 pe_debug("Deleting Preauth session(%d)",
106 pReAssocSessionEntry->peSessionId);
107 pe_delete_session(mac, pReAssocSessionEntry);
108 }
109 }
110 }
111
112 /*
113 * lim_process_ft_pre_auth_req() - process ft pre auth req
114 *
115 * @mac_ctx: global mac ctx
116 * @ft_pre_auth_req: ft preauth request
117 *
118 * In this function, we process the FT Pre Auth Req:
119 * We receive Pre-Auth, suspend link, register a call back. In the call back,
120 * we will need to accept frames from the new bssid. Send out the auth req to
121 * new AP. Start timer and when the timer is done or if we receive the Auth
122 * response. We change channel. Resume link
123 *
124 * Return: value to indicate if buffer was consumed
125 */
lim_process_ft_pre_auth_req(struct mac_context * mac_ctx,tpSirFTPreAuthReq ft_pre_auth_req)126 bool lim_process_ft_pre_auth_req(struct mac_context *mac_ctx,
127 tpSirFTPreAuthReq ft_pre_auth_req)
128 {
129 bool buf_consumed = false;
130 struct pe_session *session;
131 uint8_t session_id;
132
133 if (!ft_pre_auth_req) {
134 pe_err("tSirFTPreAuthReq is NULL");
135 return buf_consumed;
136 }
137
138 /* Get the current session entry */
139 session = pe_find_session_by_bssid(mac_ctx,
140 ft_pre_auth_req->currbssId,
141 &session_id);
142 if (!session) {
143 pe_err("Unable to find session for the bssid "
144 QDF_MAC_ADDR_FMT,
145 QDF_MAC_ADDR_REF(ft_pre_auth_req->currbssId));
146 /* Post the FT Pre Auth Response to SME */
147 lim_post_ft_pre_auth_rsp(mac_ctx, QDF_STATUS_E_FAILURE, NULL, 0,
148 session);
149 buf_consumed = true;
150 return buf_consumed;
151 }
152
153 /* Nothing to be done if the session is not in STA mode */
154 if (!LIM_IS_STA_ROLE(session)) {
155 pe_err("session is not in STA mode");
156 buf_consumed = true;
157 return buf_consumed;
158 }
159
160 /* Can set it only after sending auth */
161 session->ftPEContext.ftPreAuthStatus = QDF_STATUS_E_FAILURE;
162 session->ftPEContext.ftPreAuthSession = true;
163
164 /* Indicate that this is the session on which preauth is being done */
165 if (session->ftPEContext.pFTPreAuthReq) {
166 if (session->ftPEContext.pFTPreAuthReq->pbssDescription) {
167 qdf_mem_free(
168 session->ftPEContext.pFTPreAuthReq->pbssDescription);
169 session->ftPEContext.pFTPreAuthReq->pbssDescription =
170 NULL;
171 }
172 qdf_mem_free(session->ftPEContext.pFTPreAuthReq);
173 session->ftPEContext.pFTPreAuthReq = NULL;
174 }
175
176 /* We need information from the Pre-Auth Req. Lets save that */
177 session->ftPEContext.pFTPreAuthReq = ft_pre_auth_req;
178
179 pe_debug("PRE Auth ft_ies_length=%02x%02x%02x",
180 session->ftPEContext.pFTPreAuthReq->ft_ies[0],
181 session->ftPEContext.pFTPreAuthReq->ft_ies[1],
182 session->ftPEContext.pFTPreAuthReq->ft_ies[2]);
183 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
184 lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_PRE_AUTH_REQ_EVENT,
185 session, 0, 0);
186 #endif
187
188 /*
189 * Dont need to suspend if APs are in same channel and DUT
190 * is not in MCC state
191 */
192 if ((session->curr_op_freq !=
193 session->ftPEContext.pFTPreAuthReq->pre_auth_channel_freq)
194 || lim_is_in_mcc(mac_ctx)) {
195 /* Need to suspend link only if the channels are different */
196 pe_debug("Performing pre-auth on diff channel(session %pK)",
197 session);
198 lim_send_preauth_scan_offload(mac_ctx, session,
199 session->ftPEContext.pFTPreAuthReq);
200 } else {
201 pe_debug("Performing pre-auth on same channel (session %pK)",
202 session);
203 /* We are in the same channel. Perform pre-auth */
204 lim_perform_ft_pre_auth(mac_ctx, QDF_STATUS_SUCCESS, NULL,
205 session);
206 }
207
208 return buf_consumed;
209 }
210
211 /**
212 * lim_perform_ft_pre_auth() - Perform preauthentication
213 * @mac: Global MAC Context
214 * @status: Status Code
215 * @data: pre-auth data
216 * @pe_session: PE Session
217 *
218 * This routine will trigger the sending of authentication frame
219 * to the peer.
220 *
221 * Return: None
222 */
lim_perform_ft_pre_auth(struct mac_context * mac,QDF_STATUS status,uint32_t * data,struct pe_session * pe_session)223 void lim_perform_ft_pre_auth(struct mac_context *mac, QDF_STATUS status,
224 uint32_t *data, struct pe_session *pe_session)
225 {
226 tSirMacAuthFrameBody authFrame;
227 bool is_open = false;
228
229 if (!pe_session) {
230 pe_err("pe_session is NULL");
231 return;
232 }
233
234 if (cm_is_open_mode(pe_session->vdev))
235 is_open = true;
236
237 if (pe_session->is11Rconnection &&
238 pe_session->ftPEContext.pFTPreAuthReq) {
239 /* Only 11r assoc has FT IEs */
240 if ((!is_open) &&
241 (pe_session->ftPEContext.pFTPreAuthReq->ft_ies_length
242 == 0)) {
243 pe_err("FTIEs for Auth Req Seq 1 is absent");
244 goto preauth_fail;
245 }
246 }
247
248 if (status != QDF_STATUS_SUCCESS) {
249 pe_err("Change channel not successful for FT pre-auth");
250 goto preauth_fail;
251 }
252
253 /* Nothing to be done if the session is not in STA mode */
254 if (!LIM_IS_STA_ROLE(pe_session)) {
255 pe_err("pe_session is not in STA mode");
256 return;
257 }
258 if (cm_is_auth_type_sae(pe_session->vdev)) {
259 struct qdf_mac_addr *pre_auth_bssid = (struct qdf_mac_addr *)
260 pe_session->ftPEContext.pFTPreAuthReq->preAuthbssId;
261
262 lim_trigger_auth_req_sae(mac, pe_session, pre_auth_bssid);
263 return;
264 }
265 pe_debug("Entered wait auth2 state for FT (old session %pK)",
266 pe_session);
267 if (pe_session->is11Rconnection) {
268 /* Now we are on the right channel and need to send out Auth1
269 * and receive Auth2
270 */
271 authFrame.authAlgoNumber = eSIR_FT_AUTH;
272 } else {
273 /* Will need to make isESEconnection a enum may be for further
274 * improvements to this to match this algorithm number
275 */
276 authFrame.authAlgoNumber = eSIR_OPEN_SYSTEM;
277 }
278 authFrame.authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_1;
279 authFrame.authStatusCode = 0;
280
281 mac->lim.lim_timers.g_lim_periodic_auth_retry_timer.sessionId =
282 pe_session->peSessionId;
283
284 /* Start timer here to come back to operating channel */
285 mac->lim.lim_timers.gLimFTPreAuthRspTimer.sessionId =
286 pe_session->peSessionId;
287 if (TX_SUCCESS !=
288 tx_timer_activate(&mac->lim.lim_timers.gLimFTPreAuthRspTimer)) {
289 pe_err("FT Auth Rsp Timer Start Failed");
290 goto preauth_fail;
291 }
292 MTRACE(mac_trace(mac, TRACE_CODE_TIMER_ACTIVATE,
293 pe_session->peSessionId, eLIM_FT_PREAUTH_RSP_TIMER));
294
295 pe_debug("FT Auth Rsp Timer Started");
296 #ifdef FEATURE_WLAN_DIAG_SUPPORT
297 lim_diag_event_report(mac, WLAN_PE_DIAG_ROAM_AUTH_START_EVENT,
298 mac->lim.pe_session, QDF_STATUS_SUCCESS, QDF_STATUS_SUCCESS);
299 #endif
300 if (pe_session->ftPEContext.pFTPreAuthReq)
301 lim_send_auth_mgmt_frame(mac, &authFrame,
302 pe_session->ftPEContext.pFTPreAuthReq->preAuthbssId,
303 LIM_NO_WEP_IN_FC, pe_session);
304
305 return;
306
307 preauth_fail:
308 lim_handle_ft_pre_auth_rsp(mac, QDF_STATUS_E_FAILURE, NULL, 0, pe_session);
309 return;
310 }
311
312 /**
313 * lim_ft_setup_auth_session() - Fill the FT Session
314 * @mac: Global MAC Context
315 * @pe_session: PE Session
316 *
317 * Setup the session and the add bss req for the pre-auth AP.
318 *
319 * Return: Success or Failure Status
320 */
lim_ft_setup_auth_session(struct mac_context * mac,struct pe_session * pe_session)321 QDF_STATUS lim_ft_setup_auth_session(struct mac_context *mac,
322 struct pe_session *pe_session)
323 {
324 struct pe_session *ft_session = NULL;
325 uint8_t sessionId = 0;
326 struct sSirFTPreAuthReq *req;
327 QDF_STATUS status;
328
329 ft_session =
330 pe_find_session_by_bssid(mac, pe_session->limReAssocbssId,
331 &sessionId);
332 if (!ft_session) {
333 pe_err("No session found for bssid: "QDF_MAC_ADDR_FMT,
334 QDF_MAC_ADDR_REF(pe_session->limReAssocbssId));
335 return QDF_STATUS_E_FAILURE;
336 }
337
338 /* Nothing to be done if the session is not in STA mode */
339 if (!LIM_IS_STA_ROLE(pe_session)) {
340 pe_err("pe_session is not in STA mode");
341 return QDF_STATUS_E_FAILURE;
342 }
343
344 req = pe_session->ftPEContext.pFTPreAuthReq;
345 if (req && req->pbssDescription) {
346 status = lim_fill_ft_session(mac,
347 req->pbssDescription, ft_session,
348 pe_session, WLAN_PHYMODE_AUTO);
349 if (QDF_IS_STATUS_ERROR(status))
350 pe_err("Failed to fill ft session for vdev id %d",
351 ft_session->vdev_id);
352
353 lim_ft_prepare_add_bss_req(mac, ft_session,
354 req->pbssDescription);
355 }
356
357 return QDF_STATUS_SUCCESS;
358 }
359
360 /**
361 * lim_ft_process_pre_auth_result() - Process the Auth frame
362 * @mac: Global MAC context
363 * @pe_session: PE Session
364 *
365 * Return: None
366 */
lim_ft_process_pre_auth_result(struct mac_context * mac,struct pe_session * pe_session)367 static void lim_ft_process_pre_auth_result(struct mac_context *mac,
368 struct pe_session *pe_session)
369 {
370 if (!pe_session ||
371 !pe_session->ftPEContext.pFTPreAuthReq)
372 return;
373
374 /* Nothing to be done if the session is not in STA mode */
375 if (!LIM_IS_STA_ROLE(pe_session)) {
376 pe_err("pe_session is not in STA mode");
377 return;
378 }
379
380 if (pe_session->ftPEContext.ftPreAuthStatus == QDF_STATUS_SUCCESS) {
381 pe_session->ftPEContext.ftPreAuthStatus =
382 lim_ft_setup_auth_session(mac, pe_session);
383 }
384 /* Post the FT Pre Auth Response to SME */
385 lim_post_ft_pre_auth_rsp(mac,
386 pe_session->ftPEContext.ftPreAuthStatus,
387 pe_session->ftPEContext.saved_auth_rsp,
388 pe_session->ftPEContext.saved_auth_rsp_length,
389 pe_session);
390 }
391
392 /**
393 * lim_handle_ft_pre_auth_rsp() - Handle the Auth response
394 * @mac: Global MAC Context
395 * @status: Status Code
396 * @auth_rsp: Auth Response
397 * @auth_rsp_length: Auth response length
398 * @pe_session: PE Session
399 *
400 * Send the FT Pre Auth Response to SME whenever we have a status
401 * ready to be sent to SME
402 *
403 * SME will be the one to send it up to the supplicant to receive
404 * FTIEs which will be required for Reassoc Req.
405 *
406 * @Return: None
407 */
lim_handle_ft_pre_auth_rsp(struct mac_context * mac,QDF_STATUS status,uint8_t * auth_rsp,uint16_t auth_rsp_length,struct pe_session * pe_session)408 void lim_handle_ft_pre_auth_rsp(struct mac_context *mac, QDF_STATUS status,
409 uint8_t *auth_rsp, uint16_t auth_rsp_length,
410 struct pe_session *pe_session)
411 {
412 struct pe_session *ft_session = NULL;
413 uint8_t sessionId = 0;
414 struct bss_description *pbssDescription = NULL;
415 #ifdef FEATURE_WLAN_DIAG_SUPPORT
416 lim_diag_event_report(mac, WLAN_PE_DIAG_PRE_AUTH_RSP_EVENT,
417 pe_session, (uint16_t) status, 0);
418 #endif
419
420 /* Nothing to be done if the session is not in STA mode */
421 if (!LIM_IS_STA_ROLE(pe_session)) {
422 pe_err("pe_session is not in STA mode");
423 return;
424 }
425
426 /* Save the status of pre-auth */
427 pe_session->ftPEContext.ftPreAuthStatus = status;
428
429 /* Save the auth rsp, so we can send it to
430 * SME once we resume link
431 */
432 pe_session->ftPEContext.saved_auth_rsp_length = 0;
433 if ((auth_rsp) && (auth_rsp_length < MAX_FTIE_SIZE)) {
434 qdf_mem_copy(pe_session->ftPEContext.saved_auth_rsp,
435 auth_rsp, auth_rsp_length);
436 pe_session->ftPEContext.saved_auth_rsp_length =
437 auth_rsp_length;
438 }
439
440 if (!pe_session->ftPEContext.pFTPreAuthReq ||
441 !pe_session->ftPEContext.pFTPreAuthReq->pbssDescription) {
442 pe_err("pFTPreAuthReq or pbssDescription is NULL");
443 return;
444 }
445
446 /* Create FT session for the re-association at this point */
447 if (pe_session->ftPEContext.ftPreAuthStatus == QDF_STATUS_SUCCESS) {
448 pbssDescription =
449 pe_session->ftPEContext.pFTPreAuthReq->pbssDescription;
450 ft_session =
451 pe_create_session(mac, pbssDescription->bssId,
452 &sessionId,
453 mac->lim.max_sta_of_pe_session,
454 pe_session->bssType,
455 pe_session->vdev_id);
456 if (!ft_session) {
457 pe_err("Session not created for pre-auth 11R AP");
458 status = QDF_STATUS_E_FAILURE;
459 pe_session->ftPEContext.ftPreAuthStatus = status;
460 goto send_rsp;
461 }
462
463 sir_copy_mac_addr(ft_session->self_mac_addr,
464 pe_session->self_mac_addr);
465 sir_copy_mac_addr(ft_session->limReAssocbssId,
466 pbssDescription->bssId);
467
468 /* Update the beacon/probe filter in mac_ctx */
469 lim_set_bcn_probe_filter(mac, ft_session, 0);
470
471 if (ft_session->bssType == eSIR_INFRASTRUCTURE_MODE)
472 ft_session->limSystemRole = eLIM_STA_ROLE;
473 else
474 pe_err("Invalid bss type");
475
476 ft_session->limPrevSmeState = ft_session->limSmeState;
477 ft_session->ht_config = pe_session->ht_config;
478 ft_session->limSmeState = eLIM_SME_WT_REASSOC_STATE;
479
480 if (wlan_reg_is_24ghz_ch_freq(pe_session->ftPEContext.
481 pFTPreAuthReq->pre_auth_channel_freq))
482 ft_session->vdev_nss = mac->vdev_type_nss_2g.sta;
483 else
484 ft_session->vdev_nss = mac->vdev_type_nss_5g.sta;
485
486 /* Update the ReAssoc BSSID of the current session */
487 sir_copy_mac_addr(pe_session->limReAssocbssId,
488 pbssDescription->bssId);
489 pe_debug("created session (%pK) with id = %d BSSID = "QDF_MAC_ADDR_FMT,
490 ft_session, ft_session->peSessionId,
491 QDF_MAC_ADDR_REF(pe_session->limReAssocbssId));
492 }
493 send_rsp:
494 if ((pe_session->curr_op_freq !=
495 pe_session->ftPEContext.pFTPreAuthReq->pre_auth_channel_freq) ||
496 lim_is_in_mcc(mac)) {
497 pe_debug("Pre auth on diff freq as connected AP freq %d or mcc pe sessions exist, so abort scan",
498 pe_session->ftPEContext.pFTPreAuthReq->pre_auth_channel_freq);
499
500 /* Need to move to the original AP channel */
501 lim_process_abort_scan_ind(mac, pe_session->smeSessionId,
502 pe_session->ftPEContext.pFTPreAuthReq->scan_id,
503 mac->lim.req_id | PREAUTH_REQUESTOR_ID);
504 }
505 /*
506 * Send resp to connection manager, even in case scan needs abort,
507 * scan complete will be no-op.
508 */
509 lim_ft_process_pre_auth_result(mac, pe_session);
510 }
511
512 /*
513 * lim_process_ft_preauth_rsp_timeout() - process ft preauth rsp timeout
514 *
515 * @mac_ctx: global mac ctx
516 *
517 * This function is called if preauth response is not received from the AP
518 * within this timeout while FT in progress
519 *
520 * Return: void
521 */
lim_process_ft_preauth_rsp_timeout(struct mac_context * mac_ctx)522 void lim_process_ft_preauth_rsp_timeout(struct mac_context *mac_ctx)
523 {
524 struct pe_session *session;
525
526 /*
527 * We have failed pre auth. We need to resume link and get back on
528 * home channel
529 */
530 pe_err("FT Pre-Auth Time Out!!!!");
531 session = pe_find_session_by_session_id(mac_ctx,
532 mac_ctx->lim.lim_timers.gLimFTPreAuthRspTimer.sessionId);
533 if (!session) {
534 pe_err("Session Does not exist for given sessionID");
535 return;
536 }
537
538 /* Nothing to be done if the session is not in STA mode */
539 if (!LIM_IS_STA_ROLE(session)) {
540 pe_err("session is not in STA mode");
541 return;
542 }
543
544 /* Reset the flag to indicate preauth request session */
545 session->ftPEContext.ftPreAuthSession = false;
546
547 if (!session->ftPEContext.pFTPreAuthReq) {
548 /* Auth Rsp might already be posted to SME and ftcleanup done */
549 pe_err("pFTPreAuthReq is NULL sessionId: %d",
550 mac_ctx->lim.lim_timers.gLimFTPreAuthRspTimer.sessionId);
551 return;
552 }
553
554 /*
555 * To handle the race condition where we receive preauth rsp after
556 * timer has expired.
557 */
558 if (true ==
559 session->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed) {
560 pe_err("Auth rsp already posted to SME (session %pK)",
561 session);
562 return;
563 } else {
564 /*
565 * Here we are sending preauth rsp with failure state
566 * and which is forwarded to SME. Now, if we receive an preauth
567 * resp from AP with success it would create a FT pesession, but
568 * will be dropped in SME leaving behind the pesession. Mark
569 * Preauth rsp processed so that any rsp from AP is dropped in
570 * lim_process_auth_frame_no_session.
571 */
572 pe_debug("Auth rsp not yet posted to SME (session %pK)",
573 session);
574 session->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed = true;
575 }
576
577 /*
578 * Attempted at Pre-Auth and failed. If we are off channel. We need
579 * to get back to home channel
580 */
581 lim_handle_ft_pre_auth_rsp(mac_ctx, QDF_STATUS_E_FAILURE, NULL, 0, session);
582 }
583
584 /*
585 * lim_cm_post_preauth_rsp() - post preauth response to osif.
586 *
587 * @mac_ctx: global mac ctx
588 * @status: status code to post in auth rsp
589 * @auth_rsp: pointer to auth rsp FT ie
590 * @auth_rsp_length: len of the IE field
591 * @session: pe session
592 *
593 * post preauth response to osif.
594 *
595 * Return: void
596 */
597 static void
lim_cm_post_preauth_rsp(struct mac_context * mac_ctx,QDF_STATUS status,uint8_t * auth_rsp,uint16_t auth_rsp_length,struct pe_session * session)598 lim_cm_post_preauth_rsp(struct mac_context *mac_ctx, QDF_STATUS status,
599 uint8_t *auth_rsp, uint16_t auth_rsp_length,
600 struct pe_session *session)
601 {
602 QDF_STATUS qdf_status;
603 struct scheduler_msg rsp_msg = {0};
604 struct wlan_preauth_rsp *rsp;
605
606 rsp = qdf_mem_malloc(sizeof(*rsp));
607 if (!rsp)
608 return;
609
610 rsp->psoc = mac_ctx->psoc;
611 if (session) {
612 /* Nothing to be done if the session is not in STA mode */
613 if (!LIM_IS_STA_ROLE(session)) {
614 pe_err("session is not in STA mode");
615 qdf_mem_free(rsp);
616 return;
617 }
618 rsp->vdev_id = session->vdev_id;
619 /* The bssid of the AP we are sending Auth1 to. */
620 if (session->ftPEContext.pFTPreAuthReq)
621 qdf_mem_copy(rsp->pre_auth_bssid.bytes,
622 session->ftPEContext.
623 pFTPreAuthReq->preAuthbssId,
624 QDF_MAC_ADDR_SIZE);
625 }
626 rsp->status = status;
627
628 /* Attach the auth response now back to osif */
629 rsp->ft_ie_length = 0;
630 if (auth_rsp && (auth_rsp_length < MAX_FTIE_SIZE)) {
631 /* Only 11r assoc has FT IEs */
632 qdf_mem_copy(rsp->ft_ie, auth_rsp, auth_rsp_length);
633 rsp->ft_ie_length = auth_rsp_length;
634 }
635
636 rsp_msg.bodyptr = rsp;
637 rsp_msg.callback = cm_handle_preauth_rsp;
638
639 qdf_status = scheduler_post_message(
640 QDF_MODULE_ID_PE, QDF_MODULE_ID_OS_IF,
641 QDF_MODULE_ID_OS_IF, &rsp_msg);
642
643 if (QDF_IS_STATUS_ERROR(qdf_status)) {
644 pe_err("Failed to post preauth rsp to sme vdev_id %d",
645 rsp->vdev_id);
646 qdf_mem_free(rsp);
647 }
648 }
649
650 /*
651 * lim_post_ft_pre_auth_rsp() - post ft pre auth response to SME.
652 *
653 * @mac_ctx: global mac ctx
654 * @status: status code to post in auth rsp
655 * @auth_rsp: pointer to auth rsp FT ie
656 * @auth_rsp_length: len of the IE field
657 * @session: pe session
658 *
659 * post pre auth response to SME.
660 *
661 * Return: void
662 */
lim_post_ft_pre_auth_rsp(struct mac_context * mac_ctx,QDF_STATUS status,uint8_t * auth_rsp,uint16_t auth_rsp_length,struct pe_session * session)663 void lim_post_ft_pre_auth_rsp(struct mac_context *mac_ctx,
664 QDF_STATUS status,
665 uint8_t *auth_rsp,
666 uint16_t auth_rsp_length,
667 struct pe_session *session)
668 {
669 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
670 if (status == QDF_STATUS_SUCCESS)
671 lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_PREAUTH_DONE,
672 session, status, 0);
673 #endif
674 lim_cm_post_preauth_rsp(mac_ctx, status, auth_rsp, auth_rsp_length,
675 session);
676 }
677
678 /**
679 * lim_send_preauth_scan_offload() - Send scan command to handle preauth.
680 *
681 * @mac_ctx: Pointer to Global MAC structure
682 * @session_entry: pe session
683 * @ft_preauth_req: Preauth request with parameters
684 *
685 * Builds a single channel scan request and sends it to scan module.
686 * Scan dwell time is the time allocated to go to preauth candidate
687 * channel for auth frame exchange.
688 *
689 * Return: Status of sending message to scan module.
690 */
lim_send_preauth_scan_offload(struct mac_context * mac_ctx,struct pe_session * session_entry,tSirFTPreAuthReq * ft_preauth_req)691 QDF_STATUS lim_send_preauth_scan_offload(struct mac_context *mac_ctx,
692 struct pe_session *session_entry,
693 tSirFTPreAuthReq *ft_preauth_req)
694 {
695 struct scan_start_request *req;
696 struct wlan_objmgr_vdev *vdev;
697 uint8_t vdev_id;
698 QDF_STATUS status = QDF_STATUS_SUCCESS;
699
700 if (!session_entry) {
701 pe_err("Session entry is NULL");
702 return QDF_STATUS_E_FAILURE;
703 }
704
705 vdev_id = session_entry->smeSessionId;
706
707 req = qdf_mem_malloc(sizeof(*req));
708 if (!req)
709 return QDF_STATUS_E_NOMEM;
710
711 qdf_mem_zero(req, sizeof(*req));
712
713 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac_ctx->pdev,
714 vdev_id,
715 WLAN_LEGACY_MAC_ID);
716 if (!vdev) {
717 pe_err("vdev_id %d: vdev is NULL", vdev_id);
718 qdf_mem_free(req);
719 return QDF_STATUS_E_FAILURE;
720 }
721
722 wlan_scan_init_default_params(vdev, req);
723
724 qdf_mem_copy(req->scan_req.bssid_list,
725 (uint8_t *)ft_preauth_req->currbssId,
726 QDF_MAC_ADDR_SIZE);
727
728 req->scan_req.scan_id = wlan_scan_get_scan_id(mac_ctx->psoc);
729 if (!req->scan_req.scan_id) {
730 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
731 qdf_mem_free(req);
732 pe_err("Invalid scan ID");
733 return QDF_STATUS_E_FAILURE;
734 }
735 ft_preauth_req->scan_id = req->scan_req.scan_id;
736 req->scan_req.vdev_id = vdev_id;
737 req->scan_req.scan_req_id = mac_ctx->lim.req_id | PREAUTH_REQUESTOR_ID;
738 req->scan_req.scan_priority = SCAN_PRIORITY_VERY_HIGH;
739 req->scan_req.scan_f_passive = true;
740
741 req->scan_req.chan_list.num_chan = 1;
742 req->scan_req.chan_list.chan[0].freq =
743 ft_preauth_req->pre_auth_channel_freq;
744
745 req->scan_req.dwell_time_active = LIM_FT_PREAUTH_ACTIVE_SCAN_TIME;
746 req->scan_req.dwell_time_passive = LIM_FT_PREAUTH_PASSIVE_SCAN_TIME;
747
748 status = wlan_scan_start(req);
749 if (QDF_IS_STATUS_ERROR(status))
750 /* Don't free req here, ucfg_scan_start will do free */
751 pe_info("Issue scan req failed");
752 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
753 return status;
754 }
755
lim_preauth_scan_event_handler(struct mac_context * mac_ctx,enum sir_scan_event_type event,uint8_t vdev_id,uint32_t scan_id)756 void lim_preauth_scan_event_handler(struct mac_context *mac_ctx,
757 enum sir_scan_event_type event,
758 uint8_t vdev_id, uint32_t scan_id)
759 {
760 struct pe_session *session_entry;
761
762 session_entry = pe_find_session_by_scan_id(mac_ctx, scan_id);
763 /* Pre-auth request is sent */
764 if (session_entry) {
765 if ((event == SIR_SCAN_EVENT_FOREIGN_CHANNEL) &&
766 (session_entry->ftPEContext.ftPreAuthStatus
767 == QDF_STATUS_SUCCESS)) {
768 pe_err("Pre-auth is done, skip sending pre-auth req");
769 return;
770 }
771 } else {
772 /* For the first pre-auth request
773 * need to get it by sme session id (vdev id)
774 */
775 session_entry = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
776 }
777
778 if (!session_entry) {
779 pe_err("vdev_id :%d PeSessionId:%d does not exist", vdev_id,
780 mac_ctx->lim.lim_timers.gLimFTPreAuthRspTimer.sessionId);
781 return;
782 }
783
784 switch (event) {
785 case SIR_SCAN_EVENT_START_FAILED:
786 /* Scan command is rejected by firmware */
787 pe_err("Failed to start preauth scan");
788 lim_post_ft_pre_auth_rsp(mac_ctx, QDF_STATUS_E_FAILURE, NULL, 0,
789 session_entry);
790 return;
791
792 case SIR_SCAN_EVENT_COMPLETED:
793 /*
794 * Scan either completed successfully or or got terminated
795 * after successful auth, or timed out. Either way, STA
796 * is back to home channel. Data traffic can continue.
797 * Don't do anything as preauth timer/auth resp will take care
798 * of the sending resp to the connection manager.
799 */
800 break;
801
802 case SIR_SCAN_EVENT_FOREIGN_CHANNEL:
803 /* Sta is on candidate channel. Send auth */
804 lim_perform_ft_pre_auth(mac_ctx, QDF_STATUS_SUCCESS, NULL,
805 session_entry);
806 break;
807 default:
808 /* Don't print message for scan events that are ignored */
809 break;
810 }
811 }
812
813