1 /*
2 * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /*
21 * This file lim_process_assoc_req_frame.c contains the code
22 * for processing Re/Association Request Frame.
23 */
24 #include "cds_api.h"
25 #include "ani_global.h"
26 #include "wni_cfg.h"
27 #include "sir_api.h"
28 #include "cfg_ucfg_api.h"
29
30 #include "sch_api.h"
31 #include "utils_api.h"
32 #include "lim_types.h"
33 #include "lim_utils.h"
34 #include "lim_assoc_utils.h"
35 #include "lim_security_utils.h"
36 #include "lim_ser_des_utils.h"
37 #include "lim_admit_control.h"
38 #include "cds_packet.h"
39 #include "lim_session_utils.h"
40 #include "utils_parser.h"
41 #include "wlan_p2p_api.h"
42
43 #include "qdf_types.h"
44 #include "cds_utils.h"
45 #include "wlan_utility.h"
46 #include "wlan_crypto_global_api.h"
47 #include "lim_mlo.h"
48 #include <son_api.h>
49
50 /**
51 * lim_convert_supported_channels - Parses channel support IE
52 * @mac_ctx: A pointer to Global MAC structure
53 * @assoc_ind: A pointer to SME ASSOC/REASSOC IND
54 * @assoc_req: A pointer to ASSOC/REASSOC Request frame
55 *
56 * This function is called by lim_process_assoc_req_frame() to
57 * parse the channel support IE in the Assoc/Reassoc Request
58 * frame, and send relevant information in the SME_ASSOC_IND
59 *
60 * Return: None
61 */
lim_convert_supported_channels(struct mac_context * mac_ctx,tpLimMlmAssocInd assoc_ind,tSirAssocReq * assoc_req)62 static void lim_convert_supported_channels(struct mac_context *mac_ctx,
63 tpLimMlmAssocInd assoc_ind,
64 tSirAssocReq *assoc_req)
65 {
66 uint16_t i, j, index = 0;
67 uint8_t first_ch_no;
68 uint8_t chn_count;
69 uint8_t next_ch_no;
70 uint8_t channel_offset = 0;
71 uint32_t chan_freq;
72
73 if (assoc_req->supportedChannels.length >=
74 SIR_MAX_SUPPORTED_CHANNEL_LIST) {
75 pe_err("Number of supported channels: %d is more than MAX",
76 assoc_req->supportedChannels.length);
77 assoc_ind->supportedChannels.numChnl = 0;
78 return;
79 }
80
81 for (i = 0; i < (assoc_req->supportedChannels.length); i++) {
82 /* Get First Channel Number */
83 first_ch_no = assoc_req->supportedChannels.supportedChannels[i];
84 assoc_ind->supportedChannels.channelList[index] = first_ch_no;
85 i++;
86 index++;
87
88 /* Get Number of Channels in a Subband */
89 chn_count = assoc_req->supportedChannels.supportedChannels[i];
90 if (index >= SIR_MAX_SUPPORTED_CHANNEL_LIST) {
91 pe_warn("Ch count > max supported: %d", chn_count);
92 assoc_ind->supportedChannels.numChnl = 0;
93 return;
94 }
95 if (chn_count <= 1)
96 continue;
97 next_ch_no = first_ch_no;
98 chan_freq = wlan_reg_legacy_chan_to_freq(mac_ctx->pdev,
99 first_ch_no);
100
101 if (REG_BAND_5G == lim_get_rf_band(chan_freq))
102 channel_offset = SIR_11A_FREQUENCY_OFFSET;
103 else if (REG_BAND_2G == lim_get_rf_band(chan_freq))
104 channel_offset = SIR_11B_FREQUENCY_OFFSET;
105 else
106 continue;
107
108 for (j = 1; j < chn_count; j++) {
109 next_ch_no += channel_offset;
110 assoc_ind->supportedChannels.channelList[index]
111 = next_ch_no;
112 index++;
113 if (index >= SIR_MAX_SUPPORTED_CHANNEL_LIST) {
114 pe_warn("Ch count > supported: %d", chn_count);
115 assoc_ind->supportedChannels.numChnl = 0;
116 return;
117 }
118 }
119 }
120
121 assoc_ind->supportedChannels.numChnl = (uint8_t) index;
122 pe_debug("Send AssocInd to WSM: minPwr: %d maxPwr: %d numChnl: %d",
123 assoc_ind->powerCap.minTxPower,
124 assoc_ind->powerCap.maxTxPower,
125 assoc_ind->supportedChannels.numChnl);
126
127 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
128 assoc_req->supportedChannels.supportedChannels,
129 assoc_req->supportedChannels.length);
130 }
131
132 /**
133 * lim_check_sta_in_pe_entries() - checks if sta exists in any dph tables.
134 * @mac_ctx: Pointer to Global MAC structure
135 * @sa: Mac address of requesting peer
136 * @sessionid - session id for which session is initiated
137 * @dup_entry: pointer for duplicate entry found
138 *
139 * This function is called by lim_process_assoc_req_frame() to check if STA
140 * entry already exists in any of the PE entries of the AP. If it exists, deauth
141 * will be sent on that session and the STA deletion will happen. After this,
142 * the ASSOC request will be processed. If the STA is already in deleting phase
143 * this will return failure so that assoc req will be rejected till STA is
144 * deleted.
145 *
146 * Return: QDF_STATUS.
147 */
lim_check_sta_in_pe_entries(struct mac_context * mac_ctx,tSirMacAddr sa,uint16_t sessionid,bool * dup_entry)148 static QDF_STATUS lim_check_sta_in_pe_entries(struct mac_context *mac_ctx,
149 tSirMacAddr sa,
150 uint16_t sessionid,
151 bool *dup_entry)
152 {
153 uint8_t i;
154 uint16_t assoc_id = 0;
155 tpDphHashNode sta_ds = NULL;
156 struct pe_session *session;
157
158 *dup_entry = false;
159 for (i = 0; i < mac_ctx->lim.maxBssId; i++) {
160 session = &mac_ctx->lim.gpSession[i];
161 if (session->valid &&
162 (session->opmode == QDF_SAP_MODE)) {
163 sta_ds = dph_lookup_hash_entry(
164 mac_ctx, sa,
165 &assoc_id, &session->dph.dphHashTable);
166 if (sta_ds
167 && (!sta_ds->rmfEnabled ||
168 (sessionid != session->peSessionId))
169 ) {
170 if (sta_ds->mlmStaContext.mlmState ==
171 eLIM_MLM_WT_DEL_STA_RSP_STATE ||
172 sta_ds->mlmStaContext.mlmState ==
173 eLIM_MLM_WT_DEL_BSS_RSP_STATE ||
174 sta_ds->sta_deletion_in_progress) {
175 pe_debug(
176 "Deletion is in progress (%d) for peer:"QDF_MAC_ADDR_FMT" in mlmState %d",
177 sta_ds->sta_deletion_in_progress,
178 QDF_MAC_ADDR_REF(sta_ds->staAddr),
179 sta_ds->mlmStaContext.mlmState);
180 *dup_entry = true;
181 return QDF_STATUS_E_AGAIN;
182 }
183 sta_ds->sta_deletion_in_progress = true;
184 pe_err("Sending Disassoc and Deleting existing STA entry:"
185 QDF_MAC_ADDR_FMT,
186 QDF_MAC_ADDR_REF(
187 session->self_mac_addr));
188 lim_send_disassoc_mgmt_frame(mac_ctx,
189 REASON_UNSPEC_FAILURE,
190 (uint8_t *)sa, session, false);
191 /*
192 * Cleanup Rx path posts eWNI_SME_DISASSOC_RSP
193 * msg to SME after delete sta which will update
194 * the userspace with disconnect
195 */
196 sta_ds->mlmStaContext.cleanupTrigger =
197 eLIM_DUPLICATE_ENTRY;
198 sta_ds->mlmStaContext.disassocReason =
199 REASON_DISASSOC_DUE_TO_INACTIVITY;
200 lim_send_sme_disassoc_ind(mac_ctx, sta_ds,
201 session);
202 *dup_entry = true;
203 break;
204 }
205 }
206 }
207
208 return QDF_STATUS_SUCCESS;
209 }
210
211 /**
212 * lim_chk_sa_da() - checks source addr to destination addr of assoc req frame
213 * @mac_ctx: pointer to Global MAC structure
214 * @hdr: pointer to the MAC head
215 * @session: pointer to pe session entry
216 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
217 *
218 * Checks source addr to destination addr of assoc req frame
219 *
220 * Return: true if source and destination address are different
221 */
lim_chk_sa_da(struct mac_context * mac_ctx,tpSirMacMgmtHdr hdr,struct pe_session * session,uint8_t sub_type)222 static bool lim_chk_sa_da(struct mac_context *mac_ctx, tpSirMacMgmtHdr hdr,
223 struct pe_session *session, uint8_t sub_type)
224 {
225 if (qdf_mem_cmp((uint8_t *) hdr->sa,
226 (uint8_t *) hdr->da,
227 (uint8_t) (sizeof(tSirMacAddr))))
228 return true;
229
230 pe_err("Assoc Req rejected: wlan.sa = wlan.da");
231 lim_send_assoc_rsp_mgmt_frame(mac_ctx, STATUS_UNSPECIFIED_FAILURE,
232 1, hdr->sa, sub_type, 0, session, false);
233 return false;
234 }
235
236 /**
237 * lim_chk_assoc_req_parse_error() - checks for error in frame parsing
238 * @mac_ctx: pointer to Global MAC structure
239 * @sa: Mac address of requesting peer
240 * @session: pointer to pe session entry
241 * @assoc_req: pointer to ASSOC/REASSOC Request frame
242 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
243 * @frm_body: frame body
244 * @frame_len: frame len
245 *
246 * Checks for error in frame parsing
247 *
248 * Return: true of no error, false otherwise
249 */
lim_chk_assoc_req_parse_error(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,uint8_t * frm_body,uint32_t frame_len)250 static bool lim_chk_assoc_req_parse_error(struct mac_context *mac_ctx,
251 tSirMacAddr sa,
252 struct pe_session *session,
253 tpSirAssocReq assoc_req,
254 uint8_t sub_type, uint8_t *frm_body,
255 uint32_t frame_len)
256 {
257 QDF_STATUS qdf_status;
258 enum wlan_status_code wlan_status;
259 struct qdf_mac_addr *mld_mac;
260
261 if (sub_type == LIM_ASSOC)
262 wlan_status = sir_convert_assoc_req_frame2_struct(mac_ctx, frm_body,
263 frame_len,
264 assoc_req);
265 else
266 wlan_status = sir_convert_reassoc_req_frame2_struct(mac_ctx,
267 frm_body, frame_len, assoc_req);
268
269 if (wlan_status == STATUS_SUCCESS) {
270 qdf_status = lim_strip_and_decode_eht_cap(
271 frm_body + WLAN_ASSOC_REQ_IES_OFFSET,
272 frame_len - WLAN_ASSOC_REQ_IES_OFFSET,
273 &assoc_req->eht_cap,
274 assoc_req->he_cap,
275 session->curr_op_freq);
276 if (QDF_IS_STATUS_ERROR(qdf_status)) {
277 pe_err("Failed to extract eht cap");
278 return false;
279 }
280
281 /*
282 * If EHT capability is not present but MLO is parsed
283 * suceesssfully, remove the ML info from assoc request.
284 */
285 mld_mac = (struct qdf_mac_addr *)assoc_req->mld_mac;
286 if (!assoc_req->eht_cap.present &&
287 !qdf_is_macaddr_zero(mld_mac)) {
288 qdf_zero_macaddr(mld_mac);
289 qdf_mem_zero(&assoc_req->mlo_info,
290 sizeof(assoc_req->mlo_info));
291 }
292
293 return true;
294 }
295
296 pe_warn("Assoc Req rejected: frame parsing error. source addr:"
297 QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(sa));
298 lim_send_assoc_rsp_mgmt_frame(mac_ctx, wlan_status,
299 1, sa, sub_type, 0, session, false);
300 return false;
301 }
302
303 /**
304 * lim_chk_capab() - checks for capab match
305 * @mac_ctx: pointer to Global MAC structure
306 * @sa: Mac address of requesting peer
307 * @session: pointer to pe session entry
308 * @assoc_req: pointer to ASSOC/REASSOC Request frame
309 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
310 * @local_cap: local capabilities of SAP
311 *
312 * Checks for capab match
313 *
314 * Return: true of no error, false otherwise
315 */
lim_chk_capab(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,tSirMacCapabilityInfo * local_cap)316 static bool lim_chk_capab(struct mac_context *mac_ctx, tSirMacAddr sa,
317 struct pe_session *session, tpSirAssocReq assoc_req,
318 uint8_t sub_type, tSirMacCapabilityInfo *local_cap)
319 {
320 uint16_t temp;
321
322 if (lim_get_capability_info(mac_ctx, &temp, session) !=
323 QDF_STATUS_SUCCESS) {
324 pe_err("could not retrieve Capabilities");
325 return false;
326 }
327
328 lim_copy_u16((uint8_t *) local_cap, temp);
329
330 if (lim_compare_capabilities(mac_ctx, assoc_req,
331 local_cap, session) == false) {
332 pe_warn("Rcvd %s Req with unsupported capab from"
333 QDF_MAC_ADDR_FMT,
334 (LIM_ASSOC == sub_type) ? "Assoc" : "ReAssoc",
335 QDF_MAC_ADDR_REF(sa));
336 /*
337 * Capabilities of requesting STA does not match with
338 * local capabilities. Respond with 'unsupported capabilities'
339 * status code.
340 */
341 lim_send_assoc_rsp_mgmt_frame(
342 mac_ctx, STATUS_CAPS_UNSUPPORTED,
343 1, sa, sub_type, 0, session, false);
344 return false;
345 }
346 return true;
347 }
348
349 /**
350 * lim_chk_ssid() - checks for SSID match
351 * @mac_ctx: pointer to Global MAC structure
352 * @sa: Mac address of requesting peer
353 * @session: pointer to pe session entry
354 * @assoc_req: pointer to ASSOC/REASSOC Request frame
355 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
356 *
357 * Checks for SSID match
358 *
359 * Return: true of no error, false otherwise
360 */
lim_chk_ssid(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)361 static bool lim_chk_ssid(struct mac_context *mac_ctx, tSirMacAddr sa,
362 struct pe_session *session, tpSirAssocReq assoc_req,
363 uint8_t sub_type)
364 {
365 if (!lim_cmp_ssid(&assoc_req->ssId, session))
366 return true;
367
368 pe_err("%s Req with ssid wrong(Rcvd: " QDF_SSID_FMT " self: " QDF_SSID_FMT ") from " QDF_MAC_ADDR_FMT,
369 (LIM_ASSOC == sub_type) ? "Assoc" : "ReAssoc",
370 QDF_SSID_REF(assoc_req->ssId.length, assoc_req->ssId.ssId),
371 QDF_SSID_REF(session->ssId.length, session->ssId.ssId),
372 QDF_MAC_ADDR_REF(sa));
373
374 /*
375 * Received Re/Association Request with either Broadcast SSID OR with
376 * SSID that does not match with local one. Respond with unspecified
377 * status code.
378 */
379 lim_send_assoc_rsp_mgmt_frame(mac_ctx, STATUS_UNSPECIFIED_FAILURE,
380 1, sa, sub_type, 0, session, false);
381 return false;
382 }
383
384 /**
385 * lim_chk_rates() - checks for supported rates
386 * @mac_ctx: pointer to Global MAC structure
387 * @sa: Mac address of requesting peer
388 * @session: pointer to pe session entry
389 * @assoc_req: pointer to ASSOC/REASSOC Request frame
390 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
391 *
392 * Checks for supported rates
393 *
394 * Return: true of no error, false otherwise
395 */
lim_chk_rates(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)396 static bool lim_chk_rates(struct mac_context *mac_ctx, tSirMacAddr sa,
397 struct pe_session *session, tpSirAssocReq assoc_req,
398 uint8_t sub_type)
399 {
400 uint8_t i = 0, j = 0;
401 tSirMacRateSet basic_rates;
402 /*
403 * Verify if the requested rates are available in supported rate
404 * set or Extended rate set. Some APs are adding basic rates in
405 * Extended rateset IE
406 */
407 basic_rates.numRates = 0;
408
409 for (i = 0; i < assoc_req->supportedRates.numRates &&
410 (i < SIR_MAC_MAX_NUMBER_OF_RATES); i++) {
411 basic_rates.rate[i] = assoc_req->supportedRates.rate[i];
412 basic_rates.numRates++;
413 }
414
415 for (j = 0; (j < assoc_req->extendedRates.numRates) &&
416 (i < SIR_MAC_MAX_NUMBER_OF_RATES); i++, j++) {
417 basic_rates.rate[i] = assoc_req->extendedRates.rate[j];
418 basic_rates.numRates++;
419 }
420
421 if (lim_check_rx_basic_rates(mac_ctx, basic_rates, session) == true)
422 return true;
423
424 pe_warn("Assoc Req rejected: unsupported rates, source addr: %s"
425 QDF_MAC_ADDR_FMT,
426 (LIM_ASSOC == sub_type) ? "Assoc" : "ReAssoc",
427 QDF_MAC_ADDR_REF(sa));
428 /*
429 * Requesting STA does not support ALL BSS basic rates. Respond with
430 * 'basic rates not supported' status code.
431 */
432 lim_send_assoc_rsp_mgmt_frame(
433 mac_ctx, STATUS_ASSOC_DENIED_RATES, 1,
434 sa, sub_type, 0, session, false);
435 return false;
436 }
437
438 /**
439 * lim_chk_11g_only() - checks for non 11g STA
440 * @mac_ctx: pointer to Global MAC structure
441 * @sa: Mac address of requesting peer
442 * @session: pointer to pe session entry
443 * @assoc_req: pointer to ASSOC/REASSOC Request frame
444 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
445 *
446 * Checks for non 11g STA
447 *
448 * Return: true of no error, false otherwise
449 */
lim_chk_11g_only(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)450 static bool lim_chk_11g_only(struct mac_context *mac_ctx, tSirMacAddr sa,
451 struct pe_session *session, tpSirAssocReq assoc_req,
452 uint8_t sub_type)
453 {
454 if (LIM_IS_AP_ROLE(session) &&
455 (session->dot11mode == MLME_DOT11_MODE_11G_ONLY) &&
456 (assoc_req->HTCaps.present)) {
457 pe_err("SOFTAP was in 11G only mode, rejecting legacy STA: "
458 QDF_MAC_ADDR_FMT,
459 QDF_MAC_ADDR_REF(sa));
460 lim_send_assoc_rsp_mgmt_frame(
461 mac_ctx, STATUS_CAPS_UNSUPPORTED,
462 1, sa, sub_type, 0, session, false);
463 return false;
464 }
465 return true;
466 }
467
468 /**
469 * lim_chk_11n_only() - checks for non 11n STA
470 * @mac_ctx: pointer to Global MAC structure
471 * @sa: Mac address of requesting peer
472 * @session: pointer to pe session entry
473 * @assoc_req: pointer to ASSOC/REASSOC Request frame
474 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
475 *
476 * Checks for non 11n STA
477 *
478 * Return: true of no error, false otherwise
479 */
lim_chk_11n_only(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)480 static bool lim_chk_11n_only(struct mac_context *mac_ctx, tSirMacAddr sa,
481 struct pe_session *session, tpSirAssocReq assoc_req,
482 uint8_t sub_type)
483 {
484 if (LIM_IS_AP_ROLE(session) &&
485 (session->dot11mode == MLME_DOT11_MODE_11N_ONLY) &&
486 (!assoc_req->HTCaps.present)) {
487 pe_err("SOFTAP was in 11N only mode, rejecting legacy STA: "
488 QDF_MAC_ADDR_FMT,
489 QDF_MAC_ADDR_REF(sa));
490 lim_send_assoc_rsp_mgmt_frame(
491 mac_ctx, STATUS_CAPS_UNSUPPORTED,
492 1, sa, sub_type, 0, session, false);
493 return false;
494 }
495 return true;
496 }
497
498 /**
499 * lim_chk_11ac_only() - checks for non 11ac STA
500 * @mac_ctx: pointer to Global MAC structure
501 * @sa: Mac address of requesting peer
502 * @session: pointer to pe session entry
503 * @assoc_req: pointer to ASSOC/REASSOC Request frame
504 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
505 *
506 * Checks for non 11ac STA
507 *
508 * Return: true of no error, false otherwise
509 */
lim_chk_11ac_only(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)510 static bool lim_chk_11ac_only(struct mac_context *mac_ctx, tSirMacAddr sa,
511 struct pe_session *session, tpSirAssocReq assoc_req,
512 uint8_t sub_type)
513 {
514 tDot11fIEVHTCaps *vht_caps;
515
516 if (assoc_req->VHTCaps.present)
517 vht_caps = &assoc_req->VHTCaps;
518 else if (assoc_req->vendor_vht_ie.VHTCaps.present &&
519 session->vendor_vht_sap)
520 vht_caps = &assoc_req->vendor_vht_ie.VHTCaps;
521 else
522 vht_caps = NULL;
523
524 if (LIM_IS_AP_ROLE(session) &&
525 (session->dot11mode == MLME_DOT11_MODE_11AC_ONLY) &&
526 ((!vht_caps) || ((vht_caps) && (!vht_caps->present)))) {
527 lim_send_assoc_rsp_mgmt_frame(
528 mac_ctx, STATUS_CAPS_UNSUPPORTED,
529 1, sa, sub_type, 0, session, false);
530 pe_err("SOFTAP was in 11AC only mode, reject");
531 return false;
532 }
533 return true;
534 }
535
536 /**
537 * lim_chk_11ax_only() - checks for non 11ax STA
538 * @mac_ctx: pointer to Global MAC structure
539 * @sa: Mac address of requesting peer
540 * @session: pointer to pe session entry
541 * @assoc_req: pointer to ASSOC/REASSOC Request frame
542 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
543 *
544 * Checks for non 11ax STA
545 *
546 * Return: true of no error, false otherwise
547 */
548 #ifdef WLAN_FEATURE_11AX
lim_chk_11ax_only(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)549 static bool lim_chk_11ax_only(struct mac_context *mac_ctx, tSirMacAddr sa,
550 struct pe_session *session, tpSirAssocReq assoc_req,
551 uint8_t sub_type)
552 {
553 if (LIM_IS_AP_ROLE(session) &&
554 (session->dot11mode == MLME_DOT11_MODE_11AX_ONLY) &&
555 !assoc_req->he_cap.present) {
556 lim_send_assoc_rsp_mgmt_frame(
557 mac_ctx, STATUS_CAPS_UNSUPPORTED,
558 1, sa, sub_type, 0, session, false);
559 pe_err("SOFTAP was in 11AX only mode, reject");
560 return false;
561 }
562 return true;
563 }
564
565 /**
566 * lim_check_11ax_basic_mcs() - checks for 11ax basic MCS rates
567 * @mac_ctx: pointer to Global MAC structure
568 * @sa: Mac address of requesting peer
569 * @session: pointer to pe session entry
570 * @assoc_req: pointer to ASSOC/REASSOC Request frame
571 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
572 *
573 * Checks for non 11ax STA
574 *
575 * Return: true of no error, false otherwise
576 */
lim_check_11ax_basic_mcs(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)577 static bool lim_check_11ax_basic_mcs(struct mac_context *mac_ctx,
578 tSirMacAddr sa,
579 struct pe_session *session,
580 tpSirAssocReq assoc_req,
581 uint8_t sub_type)
582 {
583 uint16_t basic_mcs, sta_mcs, rx_mcs, tx_mcs, final_mcs;
584
585 if (LIM_IS_AP_ROLE(session) &&
586 assoc_req->he_cap.present) {
587 rx_mcs = assoc_req->he_cap.rx_he_mcs_map_lt_80;
588 tx_mcs = assoc_req->he_cap.tx_he_mcs_map_lt_80;
589 sta_mcs = HE_INTERSECT_MCS(rx_mcs, tx_mcs);
590 basic_mcs =
591 (uint16_t)mac_ctx->mlme_cfg->he_caps.he_ops_basic_mcs_nss;
592 final_mcs = HE_INTERSECT_MCS(sta_mcs, basic_mcs);
593 if (final_mcs != basic_mcs) {
594 lim_send_assoc_rsp_mgmt_frame(
595 mac_ctx,
596 STATUS_CAPS_UNSUPPORTED,
597 1, sa, sub_type, 0, session, false);
598 pe_err("STA did not support basic MCS required by SAP");
599 return false;
600 }
601 }
602 return true;
603 }
604
605 #else
lim_chk_11ax_only(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)606 static bool lim_chk_11ax_only(struct mac_context *mac_ctx, tSirMacAddr sa,
607 struct pe_session *session, tpSirAssocReq assoc_req,
608 uint8_t sub_type)
609 {
610 return true;
611 }
612
lim_check_11ax_basic_mcs(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)613 static bool lim_check_11ax_basic_mcs(struct mac_context *mac_ctx,
614 tSirMacAddr sa,
615 struct pe_session *session,
616 tpSirAssocReq assoc_req,
617 uint8_t sub_type)
618 {
619 return true;
620 }
621 #endif
622
623 /**
624 * lim_chk_11be_only() - checks for non 11be STA
625 * @mac_ctx: pointer to Global MAC structure
626 * @sa: Mac address of requesting peer
627 * @session: pointer to pe session entry
628 * @assoc_req: pointer to ASSOC/REASSOC Request frame
629 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
630 *
631 * Checks for non 11be STA
632 *
633 * Return: true if no error, false otherwise
634 */
635 #ifdef WLAN_FEATURE_11BE
lim_chk_11be_only(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)636 static bool lim_chk_11be_only(struct mac_context *mac_ctx, tSirMacAddr sa,
637 struct pe_session *session,
638 tpSirAssocReq assoc_req, uint8_t sub_type)
639 {
640 if (LIM_IS_AP_ROLE(session) &&
641 (session->dot11mode == MLME_DOT11_MODE_11BE_ONLY) &&
642 !assoc_req->eht_cap.present) {
643 lim_send_assoc_rsp_mgmt_frame(
644 mac_ctx, STATUS_CAPS_UNSUPPORTED,
645 1, sa, sub_type, 0, session, false);
646 pe_err("SOFTAP was in 11BE only mode, reject");
647 return false;
648 }
649 return true;
650 }
651 #else
lim_chk_11be_only(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)652 static bool lim_chk_11be_only(struct mac_context *mac_ctx, tSirMacAddr sa,
653 struct pe_session *session,
654 tpSirAssocReq assoc_req, uint8_t sub_type)
655 {
656 return true;
657 }
658 #endif
659
660 /**
661 * lim_process_for_spectrum_mgmt() - process assoc req for spectrum mgmt
662 * @mac_ctx: pointer to Global MAC structure
663 * @sa: Mac address of requesting peer
664 * @session: pointer to pe session entry
665 * @assoc_req: pointer to ASSOC/REASSOC Request frame
666 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
667 * @local_cap: local capabilities of SAP
668 *
669 * Checks for SSID match
670 *
671 * process assoc req for spectrum mgmt
672 */
673 static void
lim_process_for_spectrum_mgmt(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,tSirMacCapabilityInfo local_cap)674 lim_process_for_spectrum_mgmt(struct mac_context *mac_ctx, tSirMacAddr sa,
675 struct pe_session *session, tpSirAssocReq assoc_req,
676 uint8_t sub_type, tSirMacCapabilityInfo local_cap)
677 {
678 if (local_cap.spectrumMgt) {
679 QDF_STATUS status = QDF_STATUS_SUCCESS;
680 /*
681 * If station is 11h capable, then it SHOULD send all mandatory
682 * IEs in assoc request frame. Let us verify that
683 */
684 if (assoc_req->capabilityInfo.spectrumMgt) {
685 if (!((assoc_req->powerCapabilityPresent)
686 && (assoc_req->supportedChannelsPresent))) {
687 /*
688 * One or more required information elements are
689 * missing, log the peers error
690 */
691 if (!assoc_req->powerCapabilityPresent) {
692 pe_warn("LIM Info: Missing Power capability IE in %s Req from "
693 QDF_MAC_ADDR_FMT,
694 (LIM_ASSOC == sub_type) ?
695 "Assoc" : "ReAssoc",
696 QDF_MAC_ADDR_REF(sa));
697 }
698 if (!assoc_req->supportedChannelsPresent) {
699 pe_warn("LIM Info: Missing Supported channel IE in %s Req from "
700 QDF_MAC_ADDR_FMT,
701 (LIM_ASSOC == sub_type) ?
702 "Assoc" : "ReAssoc",
703 QDF_MAC_ADDR_REF(sa));
704 }
705 } else {
706 /* Assoc request has mandatory fields */
707 status =
708 lim_is_dot11h_power_capabilities_in_range(
709 mac_ctx, assoc_req, session);
710 if (QDF_STATUS_SUCCESS != status) {
711 pe_warn("LIM Info: MinTxPower(STA) > MaxTxPower(AP) in %s Req from "
712 QDF_MAC_ADDR_FMT,
713 (LIM_ASSOC == sub_type) ?
714 "Assoc" : "ReAssoc",
715 QDF_MAC_ADDR_REF(sa));
716 }
717 status = lim_is_dot11h_supported_channels_valid(
718 mac_ctx, assoc_req);
719 if (QDF_STATUS_SUCCESS != status) {
720 pe_warn("LIM Info: wrong supported channels (STA) in %s Req from "
721 QDF_MAC_ADDR_FMT,
722 (LIM_ASSOC == sub_type) ?
723 "Assoc" : "ReAssoc",
724 QDF_MAC_ADDR_REF(sa));
725 }
726 /* IEs are valid, use them if needed */
727 }
728 } /* if(assoc.capabilityInfo.spectrumMgt) */
729 else {
730 /*
731 * As per the capabilities, the spectrum management is
732 * not enabled on the station. The AP may allow the
733 * associations to happen even if spectrum management
734 * is not allowed, if the transmit power of station is
735 * below the regulatory maximum
736 */
737
738 /*
739 * TODO: presently, this is not handled. In the current
740 * implementation, the AP would allow the station to
741 * associate even if it doesn't support spectrum
742 * management.
743 */
744 }
745 } /* end of spectrum management related processing */
746 }
747
748 /**
749 * lim_chk_mcs() - checks for supported MCS
750 * @mac_ctx: pointer to Global MAC structure
751 * @sa: Mac address of requesting peer
752 * @session: pointer to pe session entry
753 * @assoc_req: pointer to ASSOC/REASSOC Request frame
754 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
755 *
756 * Checks for supported MCS
757 *
758 * Return: true of no error, false otherwise
759 */
lim_chk_mcs(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type)760 static bool lim_chk_mcs(struct mac_context *mac_ctx, tSirMacAddr sa,
761 struct pe_session *session, tpSirAssocReq assoc_req,
762 uint8_t sub_type)
763 {
764 if ((assoc_req->HTCaps.present) && (lim_check_mcs_set(mac_ctx,
765 assoc_req->HTCaps.supportedMCSSet) == false)) {
766 pe_warn("rcvd %s req with unsupported MCS Rate Set from "
767 QDF_MAC_ADDR_FMT,
768 (LIM_ASSOC == sub_type) ? "Assoc" : "ReAssoc",
769 QDF_MAC_ADDR_REF(sa));
770 /*
771 * Requesting STA does not support ALL BSS MCS basic Rate set
772 * rates. Spec does not define any status code for this
773 * scenario.
774 */
775 lim_send_assoc_rsp_mgmt_frame(
776 mac_ctx, STATUS_ASSOC_DENIED_UNSPEC,
777 1, sa, sub_type, 0, session, false);
778 return false;
779 }
780 return true;
781 }
782
783 /**
784 * lim_chk_is_11b_sta_supported() - checks if STA is 11b
785 * @mac_ctx: pointer to Global MAC structure
786 * @sa: Mac address of requesting peer
787 * @session: pointer to pe session entry
788 * @assoc_req: pointer to ASSOC/REASSOC Request frame
789 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
790 * @phy_mode: phy mode
791 *
792 * Checks if STA is 11b
793 *
794 * Return: true of no error, false otherwise
795 */
lim_chk_is_11b_sta_supported(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,uint32_t phy_mode)796 static bool lim_chk_is_11b_sta_supported(struct mac_context *mac_ctx,
797 tSirMacAddr sa,
798 struct pe_session *session,
799 tpSirAssocReq assoc_req,
800 uint8_t sub_type, uint32_t phy_mode)
801 {
802 uint32_t cfg_11g_only;
803
804 if (phy_mode == WNI_CFG_PHY_MODE_11G) {
805 cfg_11g_only = mac_ctx->mlme_cfg->sap_cfg.sap_11g_policy;
806 if (!assoc_req->extendedRatesPresent && cfg_11g_only) {
807 /*
808 * Received Re/Association Request from 11b STA when 11g
809 * only policy option is set. Reject with unspecified
810 * status code.
811 */
812 lim_send_assoc_rsp_mgmt_frame(
813 mac_ctx,
814 STATUS_ASSOC_DENIED_RATES,
815 1, sa, sub_type, 0, session, false);
816
817 pe_warn("Rejecting Re/Assoc req from 11b STA: "QDF_MAC_ADDR_FMT,
818 QDF_MAC_ADDR_REF(sa));
819
820 return false;
821 }
822 }
823 return true;
824 }
825
826 /**
827 * lim_print_ht_cap() - prints HT caps
828 * @mac_ctx: pointer to Global MAC structure
829 * @session: pointer to pe session entry
830 * @assoc_req: pointer to ASSOC/REASSOC Request frame
831 *
832 * Prints HT caps
833 *
834 * Return: void
835 */
lim_print_ht_cap(struct mac_context * mac_ctx,struct pe_session * session,tpSirAssocReq assoc_req)836 static void lim_print_ht_cap(struct mac_context *mac_ctx, struct pe_session *session,
837 tpSirAssocReq assoc_req)
838 {
839 if (!session->htCapability)
840 return;
841
842 if (assoc_req->HTCaps.present) {
843 /* The station *does* support 802.11n HT capability... */
844 pe_debug("AdvCodingCap:%d ChaWidthSet:%d PowerSave:%d greenField:%d shortGI20:%d shortGI40:%d txSTBC:%d rxSTBC:%d delayBA:%d maxAMSDUsize:%d DSSS/CCK:%d PSMP:%d stbcCntl:%d lsigTXProt:%d",
845 assoc_req->HTCaps.advCodingCap,
846 assoc_req->HTCaps.supportedChannelWidthSet,
847 assoc_req->HTCaps.mimoPowerSave,
848 assoc_req->HTCaps.greenField,
849 assoc_req->HTCaps.shortGI20MHz,
850 assoc_req->HTCaps.shortGI40MHz,
851 assoc_req->HTCaps.txSTBC,
852 assoc_req->HTCaps.rxSTBC,
853 assoc_req->HTCaps.delayedBA,
854 assoc_req->HTCaps.maximalAMSDUsize,
855 assoc_req->HTCaps.dsssCckMode40MHz,
856 assoc_req->HTCaps.psmp,
857 assoc_req->HTCaps.stbcControlFrame,
858 assoc_req->HTCaps.lsigTXOPProtection);
859 /*
860 * Make sure the STA's caps are compatible with our own:
861 * 11.15.2 Support of DSSS/CCK in 40 MHz the AP shall refuse
862 * association requests from an HT STA that has the DSSS/CCK
863 * Mode in 40 MHz subfield set to 1;
864 */
865 }
866 }
867
868 static enum wlan_status_code
lim_check_crypto_param(tpSirAssocReq assoc_req,struct wlan_crypto_params * peer_crypto_params)869 lim_check_crypto_param(tpSirAssocReq assoc_req,
870 struct wlan_crypto_params *peer_crypto_params)
871 {
872 /* TKIP/WEP is not allowed in HT/VHT mode*/
873 if (assoc_req->HTCaps.present) {
874 if ((peer_crypto_params->ucastcipherset &
875 (1 << WLAN_CRYPTO_CIPHER_TKIP)) ||
876 (peer_crypto_params->ucastcipherset &
877 (1 << WLAN_CRYPTO_CIPHER_WEP))) {
878 pe_info("TKIP/WEP cipher with HT supported client, reject assoc");
879 return STATUS_INVALID_IE;
880 }
881 }
882 return STATUS_SUCCESS;
883 }
884
885 static
lim_check_rsn_ie(struct pe_session * session,struct mac_context * mac_ctx,tpSirAssocReq assoc_req,bool * pmf_connection)886 enum wlan_status_code lim_check_rsn_ie(struct pe_session *session,
887 struct mac_context *mac_ctx,
888 tpSirAssocReq assoc_req,
889 bool *pmf_connection)
890 {
891 struct wlan_objmgr_vdev *vdev;
892 tSirMacRsnInfo *rsn_ie;
893 struct wlan_crypto_params peer_crypto_params;
894
895 rsn_ie = qdf_mem_malloc(sizeof(*rsn_ie));
896 if (!rsn_ie) {
897 pe_err("malloc failed for rsn_ie");
898 return STATUS_UNSPECIFIED_FAILURE;
899 }
900
901 rsn_ie->info[0] = WLAN_ELEMID_RSN;
902 rsn_ie->info[1] = assoc_req->rsn.length;
903
904 rsn_ie->length = assoc_req->rsn.length + 2;
905 qdf_mem_copy(&rsn_ie->info[2], assoc_req->rsn.info,
906 assoc_req->rsn.length);
907 if (wlan_crypto_check_rsn_match(mac_ctx->psoc, session->smeSessionId,
908 &rsn_ie->info[0], rsn_ie->length,
909 &peer_crypto_params)) {
910 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
911 session->smeSessionId,
912 WLAN_LEGACY_MAC_ID);
913 if (!vdev) {
914 pe_err("vdev is NULL");
915 qdf_mem_free(rsn_ie);
916 return STATUS_UNSPECIFIED_FAILURE;
917 }
918 if ((peer_crypto_params.rsn_caps &
919 WLAN_CRYPTO_RSN_CAP_MFP_ENABLED) &&
920 wlan_crypto_vdev_is_pmf_enabled(vdev))
921 *pmf_connection = true;
922
923 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
924 qdf_mem_free(rsn_ie);
925 return lim_check_crypto_param(assoc_req, &peer_crypto_params);
926
927 } else {
928 qdf_mem_free(rsn_ie);
929 return STATUS_INVALID_IE;
930 }
931
932 qdf_mem_free(rsn_ie);
933 return STATUS_SUCCESS;
934 }
935
lim_check_wpa_ie(struct pe_session * session,struct mac_context * mac_ctx,tpSirAssocReq assoc_req,tDot11fIEWPA * wpa)936 static enum wlan_status_code lim_check_wpa_ie(struct pe_session *session,
937 struct mac_context *mac_ctx,
938 tpSirAssocReq assoc_req,
939 tDot11fIEWPA *wpa)
940 {
941 uint8_t *buffer;
942 uint32_t dot11f_status, written = 0, nbuffer = WLAN_MAX_IE_LEN;
943 tSirMacRsnInfo *wpa_ie;
944 struct wlan_crypto_params peer_crypto_params;
945
946 buffer = qdf_mem_malloc(WLAN_MAX_IE_LEN);
947 if (!buffer) {
948 pe_err("malloc failed for ie buffer");
949 return STATUS_INVALID_IE;
950 }
951
952 dot11f_status = dot11f_pack_ie_wpa(mac_ctx, wpa, buffer,
953 nbuffer, &written);
954 if (DOT11F_FAILED(dot11f_status)) {
955 pe_err("Failed to re-pack the RSN IE (0x%0x8)", dot11f_status);
956 qdf_mem_free(buffer);
957 return STATUS_INVALID_IE;
958 }
959
960 wpa_ie = qdf_mem_malloc(sizeof(*wpa_ie));
961 if (!wpa_ie) {
962 pe_err("malloc failed for wpa ie");
963 qdf_mem_free(buffer);
964 return STATUS_INVALID_IE;
965 }
966
967 wpa_ie->length = (uint8_t)written;
968 qdf_mem_copy(&wpa_ie->info[0], buffer, wpa_ie->length);
969 qdf_mem_free(buffer);
970
971 if (wlan_crypto_check_wpa_match(mac_ctx->psoc, session->smeSessionId,
972 &wpa_ie->info[0], wpa_ie->length,
973 &peer_crypto_params)) {
974 qdf_mem_free(wpa_ie);
975 return lim_check_crypto_param(assoc_req, &peer_crypto_params);
976 }
977
978 qdf_mem_free(wpa_ie);
979 return STATUS_INVALID_IE;
980 }
981
982 /**
983 * lim_check_sae_pmf_cap() - check pmf capability for SAE STA
984 * @session: pointer to pe session entry
985 * @rsn: pointer to RSN
986 * @akm_type: AKM type
987 *
988 * This function checks if SAE STA is pmf capable when SAE SAP is pmf
989 * capable. Reject with eSIR_MAC_ROBUST_MGMT_FRAMES_POLICY_VIOLATION
990 * if SAE STA is pmf disable.
991 *
992 * Return: wlan_status_code
993 */
994 #if defined(WLAN_FEATURE_SAE)
lim_check_sae_pmf_cap(struct pe_session * session,tDot11fIERSN * rsn,enum ani_akm_type akm_type)995 static enum wlan_status_code lim_check_sae_pmf_cap(struct pe_session *session,
996 tDot11fIERSN *rsn,
997 enum ani_akm_type akm_type)
998 {
999 enum wlan_status_code status = STATUS_SUCCESS;
1000
1001 if (session->limRmfEnabled &&
1002 (rsn->RSN_Cap[0] & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED) == 0 &&
1003 akm_type == ANI_AKM_TYPE_SAE)
1004 status = STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
1005
1006 return status;
1007 }
1008 #else
lim_check_sae_pmf_cap(struct pe_session * session,tDot11fIERSN * rsn,enum ani_akm_type akm_type)1009 static enum wlan_status_code lim_check_sae_pmf_cap(struct pe_session *session,
1010 tDot11fIERSN *rsn,
1011 enum ani_akm_type akm_type)
1012 {
1013 return STATUS_SUCCESS;
1014 }
1015 #endif
1016
1017 /**
1018 * lim_check_wpa_rsn_ie() - wpa and rsn ie related checks
1019 * @session: pointer to pe session entry
1020 * @mac_ctx: pointer to Global MAC structure
1021 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
1022 * @sa: Mac address of requesting peer
1023 * @assoc_req: pointer to ASSOC/REASSOC Request frame
1024 * @pmf_connection: flag indicating pmf connection
1025 * @akm_type: AKM type
1026 *
1027 * This function checks if wpa/rsn IE is present and validates
1028 * ie version, length and mismatch.
1029 *
1030 * Return: true if no error, false otherwise
1031 */
lim_check_wpa_rsn_ie(struct pe_session * session,struct mac_context * mac_ctx,uint8_t sub_type,tSirMacAddr sa,tpSirAssocReq assoc_req,bool * pmf_connection,enum ani_akm_type * akm_type)1032 static bool lim_check_wpa_rsn_ie(struct pe_session *session,
1033 struct mac_context *mac_ctx,
1034 uint8_t sub_type, tSirMacAddr sa,
1035 tpSirAssocReq assoc_req, bool *pmf_connection,
1036 enum ani_akm_type *akm_type)
1037 {
1038 uint32_t ret;
1039 tDot11fIEWPA dot11f_ie_wpa = {0};
1040 tDot11fIERSN dot11f_ie_rsn = {0};
1041 enum wlan_status_code status = STATUS_SUCCESS;
1042
1043 /*
1044 * Clear the buffers so that frame parser knows that there isn't a
1045 * previously decoded IE in these buffers
1046 */
1047 qdf_mem_zero((uint8_t *) &dot11f_ie_rsn, sizeof(dot11f_ie_rsn));
1048 qdf_mem_zero((uint8_t *) &dot11f_ie_wpa, sizeof(dot11f_ie_wpa));
1049 pe_debug("RSN enabled auth, Re/Assoc req from STA: "
1050 QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(sa));
1051
1052 if (assoc_req->rsnPresent) {
1053 if (!(assoc_req->rsn.length)) {
1054 pe_warn("Re/Assoc rejected from: "
1055 QDF_MAC_ADDR_FMT,
1056 QDF_MAC_ADDR_REF(sa));
1057 /*
1058 * rcvd Assoc req frame with RSN IE but
1059 * length is zero
1060 */
1061 lim_send_assoc_rsp_mgmt_frame(
1062 mac_ctx, STATUS_INVALID_IE, 1,
1063 sa, sub_type, 0, session, false);
1064 return false;
1065 }
1066
1067 /* Unpack the RSN IE */
1068 ret = dot11f_unpack_ie_rsn(mac_ctx,
1069 &assoc_req->rsn.info[0],
1070 assoc_req->rsn.length,
1071 &dot11f_ie_rsn, false);
1072 if (!DOT11F_SUCCEEDED(ret)) {
1073 pe_err("Invalid RSN IE");
1074 lim_send_assoc_rsp_mgmt_frame(
1075 mac_ctx, STATUS_INVALID_IE, 1,
1076 sa, sub_type, 0, session, false);
1077 return false;
1078 }
1079
1080 /* Check if the RSN version is supported */
1081 if (SIR_MAC_OUI_VERSION_1 == dot11f_ie_rsn.version) {
1082 /* check the groupwise and pairwise cipher suites */
1083 status = lim_check_rsn_ie(session, mac_ctx, assoc_req,
1084 pmf_connection);
1085 if (status != STATUS_SUCCESS) {
1086 pe_warn("Re/Assoc rejected from: "
1087 QDF_MAC_ADDR_FMT,
1088 QDF_MAC_ADDR_REF(sa));
1089
1090 lim_send_assoc_rsp_mgmt_frame(
1091 mac_ctx, status, 1, sa, sub_type,
1092 0, session, false);
1093 return false;
1094 }
1095 } else {
1096 pe_warn("Re/Assoc rejected from: " QDF_MAC_ADDR_FMT,
1097 QDF_MAC_ADDR_REF(sa));
1098 /*
1099 * rcvd Assoc req frame with RSN IE but
1100 * IE version is wrong
1101 */
1102 lim_send_assoc_rsp_mgmt_frame(
1103 mac_ctx,
1104 STATUS_UNSUPPORTED_RSN_IE_VERSION,
1105 1, sa, sub_type, 0, session, false);
1106 return false;
1107 }
1108 *akm_type = lim_translate_rsn_oui_to_akm_type(
1109 dot11f_ie_rsn.akm_suite[0]);
1110
1111 status = lim_check_sae_pmf_cap(session, &dot11f_ie_rsn,
1112 *akm_type);
1113 if (status != STATUS_SUCCESS) {
1114 /* Reject pmf disable SAE STA */
1115 pe_warn("Re/Assoc rejected from: " QDF_MAC_ADDR_FMT,
1116 QDF_MAC_ADDR_REF(sa));
1117 lim_send_assoc_rsp_mgmt_frame(mac_ctx, status,
1118 1, sa, sub_type,
1119 0, session, false);
1120 return false;
1121 }
1122
1123 } else if (assoc_req->wpaPresent) {
1124 if (!(assoc_req->wpa.length)) {
1125 pe_warn("Re/Assoc rejected from: "
1126 QDF_MAC_ADDR_FMT,
1127 QDF_MAC_ADDR_REF(sa));
1128
1129 /* rcvd Assoc req frame with invalid WPA IE length */
1130 lim_send_assoc_rsp_mgmt_frame(
1131 mac_ctx, STATUS_INVALID_IE, 1,
1132 sa, sub_type, 0, session, false);
1133 return false;
1134 }
1135 /* Unpack the WPA IE */
1136 ret = dot11f_unpack_ie_wpa(mac_ctx,
1137 &assoc_req->wpa.info[4],
1138 (assoc_req->wpa.length - 4),
1139 &dot11f_ie_wpa, false);
1140 if (!DOT11F_SUCCEEDED(ret)) {
1141 pe_err("Invalid WPA IE");
1142 lim_send_assoc_rsp_mgmt_frame(
1143 mac_ctx, STATUS_INVALID_IE, 1,
1144 sa, sub_type, 0, session, false);
1145 return false;
1146 }
1147
1148 /* check the groupwise and pairwise cipher suites*/
1149 status = lim_check_wpa_ie(session, mac_ctx, assoc_req,
1150 &dot11f_ie_wpa);
1151 if (status != STATUS_SUCCESS) {
1152 pe_warn("Re/Assoc rejected from: "
1153 QDF_MAC_ADDR_FMT,
1154 QDF_MAC_ADDR_REF(sa));
1155 /*
1156 * rcvd Assoc req frame with WPA IE
1157 * but there is mismatch
1158 */
1159 lim_send_assoc_rsp_mgmt_frame(
1160 mac_ctx, status, 1,
1161 sa, sub_type, 0, session, false);
1162 return false;
1163 }
1164 *akm_type = lim_translate_rsn_oui_to_akm_type(
1165 dot11f_ie_wpa.auth_suites[0]);
1166 } else {
1167 if ((session->gStartBssRSNIe.present ||
1168 session->gStartBssWPAIe.present) &&
1169 session->opmode == QDF_SAP_MODE) {
1170 pe_warn("STA does not support RSN and WPA!");
1171 lim_send_assoc_rsp_mgmt_frame(
1172 mac_ctx, STATUS_NOT_SUPPORTED_AUTH_ALG, 1,
1173 sa, sub_type, 0, session, false);
1174 return false;
1175 }
1176 }
1177
1178 return true;
1179 }
1180
1181 /**
1182 * lim_chk_n_process_wpa_rsn_ie() - wpa ie related checks
1183 * @mac_ctx: pointer to Global MAC structure
1184 * @sa: Mac address of requesting peer
1185 * @session: pointer to pe session entry
1186 * @assoc_req: pointer to ASSOC/REASSOC Request frame
1187 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
1188 * @pmf_connection: flag indicating pmf connection
1189 * @akm_type: AKM type
1190 *
1191 * wpa ie related checks
1192 *
1193 * Return: true if no error, false otherwise
1194 */
lim_chk_n_process_wpa_rsn_ie(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,bool * pmf_connection,enum ani_akm_type * akm_type)1195 static bool lim_chk_n_process_wpa_rsn_ie(struct mac_context *mac_ctx,
1196 tSirMacAddr sa,
1197 struct pe_session *session,
1198 tpSirAssocReq assoc_req,
1199 uint8_t sub_type,
1200 bool *pmf_connection,
1201 enum ani_akm_type *akm_type)
1202 {
1203 const uint8_t *wps_ie = NULL;
1204
1205 /* if additional IE is present, check if it has WscIE */
1206 if (assoc_req->addIEPresent && assoc_req->addIE.length)
1207 wps_ie = limGetWscIEPtr(mac_ctx, assoc_req->addIE.addIEdata,
1208 assoc_req->addIE.length);
1209 else
1210 pe_debug("Assoc req addIEPresent: %d addIE length: %d",
1211 assoc_req->addIEPresent, assoc_req->addIE.length);
1212
1213 /* when wps_ie is present, RSN/WPA IE is ignored */
1214 if (!wps_ie) {
1215 /* check whether RSN IE is present */
1216 if (LIM_IS_AP_ROLE(session) &&
1217 session->pLimStartBssReq->privacy &&
1218 session->pLimStartBssReq->rsnIE.length)
1219 return lim_check_wpa_rsn_ie(session, mac_ctx, sub_type,
1220 sa, assoc_req, pmf_connection,
1221 akm_type);
1222 } else {
1223 pe_debug("Assoc req WSE IE is present");
1224 }
1225 return true;
1226 }
1227
1228 /**
1229 * lim_process_assoc_req_no_sta_ctx() - process assoc req for no sta ctx present
1230 * @mac_ctx: pointer to Global MAC structure
1231 * @sa: Mac address of requesting peer
1232 * @session: pointer to pe session entry
1233 * @assoc_req: pointer to ASSOC/REASSOC Request frame
1234 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
1235 * @sta_pre_auth_ctx: sta pre auth context
1236 * @sta_ds: station dph entry
1237 * @auth_type: indicates security type
1238 * @partner_peer_idx: partner peer idx
1239 *
1240 * Process assoc req for no sta ctx present
1241 *
1242 * Return: true of no error, false otherwise
1243 */
lim_process_assoc_req_no_sta_ctx(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,struct tLimPreAuthNode * sta_pre_auth_ctx,tpDphHashNode sta_ds,tAniAuthType * auth_type,uint16_t partner_peer_idx)1244 static bool lim_process_assoc_req_no_sta_ctx(struct mac_context *mac_ctx,
1245 tSirMacAddr sa, struct pe_session *session,
1246 tpSirAssocReq assoc_req, uint8_t sub_type,
1247 struct tLimPreAuthNode *sta_pre_auth_ctx,
1248 tpDphHashNode sta_ds, tAniAuthType *auth_type,
1249 uint16_t partner_peer_idx)
1250 {
1251 /* Requesting STA is not currently associated */
1252 if (pe_get_current_stas_count(mac_ctx) ==
1253 mac_ctx->mlme_cfg->sap_cfg.assoc_sta_limit) {
1254 /*
1255 * Maximum number of STAs that AP can handle reached.
1256 * Send Association response to peer MAC entity
1257 */
1258 pe_info_rl("Max Sta count reached : %d",
1259 mac_ctx->lim.maxStation);
1260 lim_reject_association(mac_ctx, sa, sub_type, false,
1261 (tAniAuthType)0, 0, false,
1262 STATUS_UNSPECIFIED_FAILURE,
1263 session);
1264 return false;
1265 }
1266 /* Check if STA is pre-authenticated. */
1267 if ((!sta_pre_auth_ctx && !partner_peer_idx) ||
1268 (sta_pre_auth_ctx && sta_pre_auth_ctx->mlmState !=
1269 eLIM_MLM_AUTHENTICATED_STATE)) {
1270 /*
1271 * STA is not pre-authenticated yet requesting Re/Association
1272 * before Authentication. OR STA is in the process of getting
1273 * authenticated and sent Re/Association request. Send
1274 * Deauthentication frame with 'prior authentication required'
1275 * reason code.
1276 */
1277 lim_send_deauth_mgmt_frame(mac_ctx,
1278 REASON_STA_NOT_AUTHENTICATED,
1279 sa, session, false);
1280
1281 pe_warn("rcvd %s req, sessionid: %d, without pre-auth ctx"
1282 QDF_MAC_ADDR_FMT,
1283 (LIM_ASSOC == sub_type) ? "Assoc" : "ReAssoc",
1284 session->peSessionId, QDF_MAC_ADDR_REF(sa));
1285 return false;
1286 }
1287 if (partner_peer_idx) {
1288 if (!lim_mlo_partner_auth_type(session, partner_peer_idx,
1289 auth_type)) {
1290 pe_err("can't get partner auth type");
1291 return false;
1292 }
1293 } else {
1294 /* Delete 'pre-auth' context of STA */
1295 *auth_type = sta_pre_auth_ctx->authType;
1296 if (sta_pre_auth_ctx->authType == eSIR_AUTH_TYPE_SAE)
1297 assoc_req->is_sae_authenticated = true;
1298 lim_delete_pre_auth_node(mac_ctx, sa);
1299 }
1300 /* All is well. Assign AID (after else part) */
1301 return true;
1302 }
1303
1304 static inline void
lim_delete_pmf_query_timer(tpDphHashNode sta_ds)1305 lim_delete_pmf_query_timer(tpDphHashNode sta_ds)
1306 {
1307 if (!sta_ds->rmfEnabled)
1308 return;
1309
1310 if (tx_timer_running(&sta_ds->pmfSaQueryTimer))
1311 tx_timer_deactivate(&sta_ds->pmfSaQueryTimer);
1312 tx_timer_delete(&sta_ds->pmfSaQueryTimer);
1313 }
1314
1315 /**
1316 * lim_process_assoc_req_sta_ctx() - process assoc req for sta context present
1317 * @mac_ctx: pointer to Global MAC structure
1318 * @sa: Mac address of requesting peer
1319 * @session: pointer to pe session entry
1320 * @assoc_req: pointer to ASSOC/REASSOC Request frame
1321 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
1322 * @sta_pre_auth_ctx: sta pre auth context
1323 * @sta_ds: station dph entry
1324 * @peer_idx: peer index
1325 * @auth_type: indicates security type
1326 * @update_ctx: indicates if STA context already exist
1327 *
1328 * Process assoc req for sta context present
1329 *
1330 * Return: true of no error, false otherwise
1331 */
lim_process_assoc_req_sta_ctx(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,struct tLimPreAuthNode * sta_pre_auth_ctx,tpDphHashNode sta_ds,uint16_t peer_idx,tAniAuthType * auth_type,uint8_t * update_ctx)1332 static bool lim_process_assoc_req_sta_ctx(struct mac_context *mac_ctx,
1333 tSirMacAddr sa, struct pe_session *session,
1334 tpSirAssocReq assoc_req, uint8_t sub_type,
1335 struct tLimPreAuthNode *sta_pre_auth_ctx,
1336 tpDphHashNode sta_ds, uint16_t peer_idx,
1337 tAniAuthType *auth_type, uint8_t *update_ctx)
1338 {
1339 /* Drop if STA deletion is in progress or not in established state */
1340 if (sta_ds->sta_deletion_in_progress ||
1341 (sta_ds->mlmStaContext.mlmState !=
1342 eLIM_MLM_LINK_ESTABLISHED_STATE)) {
1343 pe_debug("%s: peer:"QDF_MAC_ADDR_FMT" in mlmState %d (%s) and sta del %d",
1344 (sub_type == LIM_ASSOC) ? "Assoc" : "ReAssoc",
1345 QDF_MAC_ADDR_REF(sta_ds->staAddr),
1346 sta_ds->mlmStaContext.mlmState,
1347 lim_mlm_state_str(sta_ds->mlmStaContext.mlmState),
1348 sta_ds->sta_deletion_in_progress);
1349 return false;
1350 }
1351
1352 /* STA sent assoc req frame while already in 'associated' state */
1353
1354 pe_debug("Re/Assoc request from station that is already associated");
1355 pe_debug("PMF enabled: %d, SA Query state: %d",
1356 sta_ds->rmfEnabled, sta_ds->pmfSaQueryState);
1357 if (sta_ds->rmfEnabled) {
1358 switch (sta_ds->pmfSaQueryState) {
1359 /*
1360 * start SA Query procedure, respond to Association Request with
1361 * try again later
1362 */
1363 case DPH_SA_QUERY_NOT_IN_PROGRESS:
1364 /*
1365 * We should reset the retry counter before we start
1366 * the SA query procedure, otherwise in next set of SA
1367 * query procedure we will end up using the stale value.
1368 */
1369 sta_ds->pmfSaQueryRetryCount = 0;
1370 lim_send_assoc_rsp_mgmt_frame(
1371 mac_ctx, STATUS_ASSOC_REJECTED_TEMPORARILY, 1,
1372 sa, sub_type, sta_ds, session, false);
1373 lim_send_sa_query_request_frame(mac_ctx,
1374 (uint8_t *) &(sta_ds->pmfSaQueryCurrentTransId),
1375 sa, session);
1376 sta_ds->pmfSaQueryStartTransId =
1377 sta_ds->pmfSaQueryCurrentTransId;
1378 sta_ds->pmfSaQueryCurrentTransId++;
1379
1380 /* start timer for SA Query retry */
1381 if (tx_timer_activate(&sta_ds->pmfSaQueryTimer)
1382 != TX_SUCCESS) {
1383 pe_err("PMF SA Query timer start failed!");
1384 return false;
1385 }
1386 sta_ds->pmfSaQueryState = DPH_SA_QUERY_IN_PROGRESS;
1387 return false;
1388 /*
1389 * SA Query procedure still going, respond to Association
1390 * Request with try again later
1391 */
1392 case DPH_SA_QUERY_IN_PROGRESS:
1393 lim_send_assoc_rsp_mgmt_frame(
1394 mac_ctx, STATUS_ASSOC_REJECTED_TEMPORARILY, 1,
1395 sa, sub_type, 0, session, false);
1396 return false;
1397
1398 /*
1399 * SA Query procedure timed out, accept Association
1400 * Request normally
1401 */
1402 case DPH_SA_QUERY_TIMED_OUT:
1403 sta_ds->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS;
1404 break;
1405 }
1406 }
1407
1408 /* no change in the capability so drop the frame */
1409 if ((sub_type == LIM_ASSOC) &&
1410 (!qdf_mem_cmp(&sta_ds->mlmStaContext.capabilityInfo,
1411 &assoc_req->capabilityInfo,
1412 sizeof(tSirMacCapabilityInfo)))) {
1413 pe_err("Received Assoc req in state: %X STAid: %d",
1414 sta_ds->mlmStaContext.mlmState, peer_idx);
1415 return false;
1416 }
1417
1418 /*
1419 * STA sent Re/association Request frame while already in
1420 * 'associated' state. Update STA capabilities and send
1421 * Association response frame with same AID
1422 */
1423 pe_debug("Rcvd Assoc req from STA already connected");
1424 sta_ds->mlmStaContext.capabilityInfo =
1425 assoc_req->capabilityInfo;
1426 if (sta_pre_auth_ctx && (sta_pre_auth_ctx->mlmState ==
1427 eLIM_MLM_AUTHENTICATED_STATE)) {
1428 /* STA has triggered pre-auth again */
1429 *auth_type = sta_pre_auth_ctx->authType;
1430 lim_delete_pre_auth_node(mac_ctx, sa);
1431 } else {
1432 *auth_type = sta_ds->mlmStaContext.authType;
1433 }
1434
1435 *update_ctx = true;
1436 /* Free pmf query timer before resetting the sta_ds */
1437 lim_delete_pmf_query_timer(sta_ds);
1438 if (dph_init_sta_state(mac_ctx, sa, peer_idx,
1439 &session->dph.dphHashTable) == NULL) {
1440 pe_err("could not Init STAid: %d", peer_idx);
1441 return false;
1442 }
1443
1444 return true;
1445 }
1446
1447 /**
1448 * lim_chk_wmm() - wmm related checks
1449 * @mac_ctx: pointer to Global MAC structure
1450 * @sa: Mac address of requesting peer
1451 * @session: pointer to pe session entry
1452 * @assoc_req: pointer to ASSOC/REASSOC Request frame
1453 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
1454 * @qos_mode: qos mode
1455 *
1456 * wmm related checks
1457 *
1458 * Return: true of no error, false otherwise
1459 */
lim_chk_wmm(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,tHalBitVal qos_mode)1460 static bool lim_chk_wmm(struct mac_context *mac_ctx, tSirMacAddr sa,
1461 struct pe_session *session, tpSirAssocReq assoc_req,
1462 uint8_t sub_type, tHalBitVal qos_mode)
1463 {
1464 tHalBitVal wme_mode;
1465
1466 limGetWmeMode(session, &wme_mode);
1467 if ((qos_mode == eHAL_SET) || (wme_mode == eHAL_SET)) {
1468 /*
1469 * for a qsta, check if the requested Traffic spec is admissible
1470 * for a non-qsta check if the sta can be admitted
1471 */
1472 if (assoc_req->addtsPresent) {
1473 uint8_t tspecIdx = 0;
1474
1475 if (lim_admit_control_add_ts(
1476 mac_ctx, sa,
1477 &(assoc_req->addtsReq),
1478 &(assoc_req->qosCapability),
1479 0, false, NULL, &tspecIdx, session) !=
1480 QDF_STATUS_SUCCESS) {
1481 pe_warn("AdmitControl: TSPEC rejected");
1482 lim_send_assoc_rsp_mgmt_frame(
1483 mac_ctx, REASON_NO_BANDWIDTH,
1484 1, sa, sub_type, 0, session,
1485 false);
1486 return false;
1487 }
1488 } else if (lim_admit_control_add_sta(mac_ctx, sa, false)
1489 != QDF_STATUS_SUCCESS) {
1490 pe_warn("AdmitControl: Sta rejected");
1491 lim_send_assoc_rsp_mgmt_frame(
1492 mac_ctx, REASON_NO_BANDWIDTH, 1,
1493 sa, sub_type, 0, session, false);
1494 return false;
1495 }
1496 /* else all ok */
1497 pe_debug("AdmitControl: Sta OK!");
1498 }
1499 return true;
1500 }
1501
lim_update_sta_ds_op_classes(tpSirAssocReq assoc_req,tpDphHashNode sta_ds)1502 static void lim_update_sta_ds_op_classes(tpSirAssocReq assoc_req,
1503 tpDphHashNode sta_ds)
1504 {
1505 qdf_mem_copy(&sta_ds->supp_operating_classes,
1506 &assoc_req->supp_operating_classes,
1507 sizeof(tDot11fIESuppOperatingClasses));
1508 }
1509
lim_is_ocv_enable_in_assoc_req(struct mac_context * mac_ctx,struct sSirAssocReq * assoc_req)1510 static bool lim_is_ocv_enable_in_assoc_req(struct mac_context *mac_ctx,
1511 struct sSirAssocReq *assoc_req)
1512 {
1513 uint32_t ret;
1514 tDot11fIERSN dot11f_ie_rsn = {0};
1515
1516 if ((assoc_req->rsnPresent) && !(assoc_req->rsn.length))
1517 return false;
1518
1519 /* Unpack the RSN IE */
1520 ret = dot11f_unpack_ie_rsn(mac_ctx, &assoc_req->rsn.info[0],
1521 assoc_req->rsn.length, &dot11f_ie_rsn,
1522 false);
1523 if (!DOT11F_SUCCEEDED(ret))
1524 return false;
1525
1526 if (*(uint16_t *)&dot11f_ie_rsn.RSN_Cap &
1527 WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED)
1528 return true;
1529
1530 return false;
1531 }
1532
1533 /**
1534 * lim_update_sta_ds() - updates ds dph entry
1535 * @mac_ctx: pointer to Global MAC structure
1536 * @sa: Mac address of requesting peer
1537 * @session: pointer to pe session entry
1538 * @assoc_req: pointer to ASSOC/REASSOC Request frame pointer
1539 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
1540 * @sta_ds: station dph entry
1541 * @auth_type: indicates security type
1542 * @akm_type: indicates security type in akm
1543 * @assoc_req_copied: boolean to indicate if assoc req was copied to tmp above
1544 * @peer_idx: peer index
1545 * @qos_mode: qos mode
1546 * @pmf_connection: flag indicating pmf connection
1547 * @force_1x1: Flag to check if the HT capable STA needs to be downgraded to 1x1
1548 * nss.
1549 *
1550 * Updates ds dph entry
1551 *
1552 * Return: true of no error, false otherwise
1553 */
lim_update_sta_ds(struct mac_context * mac_ctx,tSirMacAddr sa,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,tpDphHashNode sta_ds,tAniAuthType auth_type,enum ani_akm_type akm_type,bool * assoc_req_copied,uint16_t peer_idx,tHalBitVal qos_mode,bool pmf_connection,bool force_1x1)1554 static bool lim_update_sta_ds(struct mac_context *mac_ctx, tSirMacAddr sa,
1555 struct pe_session *session,
1556 tpSirAssocReq assoc_req,
1557 uint8_t sub_type, tpDphHashNode sta_ds,
1558 tAniAuthType auth_type,
1559 enum ani_akm_type akm_type,
1560 bool *assoc_req_copied, uint16_t peer_idx,
1561 tHalBitVal qos_mode, bool pmf_connection,
1562 bool force_1x1)
1563 {
1564 tHalBitVal wme_mode, wsm_mode;
1565 uint8_t *ht_cap_ie = NULL;
1566 tPmfSaQueryTimerId timer_id;
1567 uint16_t retry_interval;
1568 tDot11fIEVHTCaps *vht_caps;
1569 tpSirAssocReq tmp_assoc_req;
1570
1571 if (assoc_req->VHTCaps.present)
1572 vht_caps = &assoc_req->VHTCaps;
1573 else if (assoc_req->vendor_vht_ie.VHTCaps.present &&
1574 session->vendor_vht_sap)
1575 vht_caps = &assoc_req->vendor_vht_ie.VHTCaps;
1576 else
1577 vht_caps = NULL;
1578
1579 /*
1580 * check here if the parsedAssocReq already pointing to the assoc_req
1581 * and free it before assigning this new assoc_req
1582 */
1583 if (session->parsedAssocReq) {
1584 tmp_assoc_req = session->parsedAssocReq[sta_ds->assocId];
1585 if (tmp_assoc_req) {
1586 lim_free_assoc_req_frm_buf(tmp_assoc_req);
1587 qdf_mem_free(tmp_assoc_req);
1588 tmp_assoc_req = NULL;
1589 }
1590
1591 session->parsedAssocReq[sta_ds->assocId] = assoc_req;
1592 *assoc_req_copied = true;
1593 }
1594 if (!assoc_req->wmeInfoPresent) {
1595 sta_ds->mlmStaContext.htCapability = 0;
1596 sta_ds->mlmStaContext.vhtCapability = 0;
1597 } else {
1598 sta_ds->mlmStaContext.htCapability = assoc_req->HTCaps.present;
1599 if ((vht_caps) && vht_caps->present)
1600 sta_ds->mlmStaContext.vhtCapability = vht_caps->present;
1601 else
1602 sta_ds->mlmStaContext.vhtCapability = false;
1603 }
1604
1605 lim_update_stads_he_capable(sta_ds, assoc_req);
1606 lim_update_stads_eht_capable(sta_ds, assoc_req);
1607 sta_ds->qos.addtsPresent =
1608 (assoc_req->addtsPresent == 0) ? false : true;
1609 sta_ds->qos.addts = assoc_req->addtsReq;
1610 sta_ds->qos.capability = assoc_req->qosCapability;
1611 /*
1612 * short slot and short preamble should be updated before doing
1613 * limaddsta
1614 */
1615 sta_ds->shortPreambleEnabled =
1616 (uint8_t) assoc_req->capabilityInfo.shortPreamble;
1617 sta_ds->shortSlotTimeEnabled =
1618 (uint8_t) assoc_req->capabilityInfo.shortSlotTime;
1619
1620 sta_ds->valid = 0;
1621 sta_ds->mlmStaContext.authType = auth_type;
1622 sta_ds->mlmStaContext.akm_type = akm_type;
1623 sta_ds->staType = STA_ENTRY_PEER;
1624 sta_ds->mlmStaContext.force_1x1 = force_1x1;
1625
1626 pe_debug("auth_type = %d, akm_type = %d", auth_type, akm_type);
1627
1628 /*
1629 * TODO: If listen interval is more than certain limit, reject the
1630 * association. Need to check customer requirements and then implement.
1631 */
1632 sta_ds->mlmStaContext.listenInterval = assoc_req->listenInterval;
1633 sta_ds->mlmStaContext.capabilityInfo = assoc_req->capabilityInfo;
1634
1635 if (IS_DOT11_MODE_HT(session->dot11mode) &&
1636 sta_ds->mlmStaContext.htCapability) {
1637 sta_ds->htGreenfield = (uint8_t) assoc_req->HTCaps.greenField;
1638 sta_ds->htAMpduDensity = assoc_req->HTCaps.mpduDensity;
1639 sta_ds->htDsssCckRate40MHzSupport =
1640 (uint8_t) assoc_req->HTCaps.dsssCckMode40MHz;
1641 sta_ds->htLsigTXOPProtection =
1642 (uint8_t) assoc_req->HTCaps.lsigTXOPProtection;
1643 sta_ds->htMaxAmsduLength =
1644 (uint8_t) assoc_req->HTCaps.maximalAMSDUsize;
1645 sta_ds->htMaxRxAMpduFactor = assoc_req->HTCaps.maxRxAMPDUFactor;
1646 sta_ds->htMIMOPSState = assoc_req->HTCaps.mimoPowerSave;
1647
1648 /* assoc_req will be copied to session->parsedAssocReq later */
1649 ht_cap_ie = ((uint8_t *) &assoc_req->HTCaps) + 1;
1650
1651 if (session->ht_config.short_gi_20_mhz) {
1652 sta_ds->htShortGI20Mhz =
1653 (uint8_t)assoc_req->HTCaps.shortGI20MHz;
1654 } else {
1655 /* Unset htShortGI20Mhz in ht_caps*/
1656 *ht_cap_ie &= ~(1 << SIR_MAC_HT_CAP_SHORTGI20MHZ_S);
1657 sta_ds->htShortGI20Mhz = 0;
1658 }
1659
1660 if (session->ht_config.short_gi_40_mhz) {
1661 sta_ds->htShortGI40Mhz =
1662 (uint8_t)assoc_req->HTCaps.shortGI40MHz;
1663 } else {
1664 /* Unset htShortGI40Mhz in ht_caps */
1665 *ht_cap_ie &= ~(1 << SIR_MAC_HT_CAP_SHORTGI40MHZ_S);
1666 sta_ds->htShortGI40Mhz = 0;
1667 }
1668
1669 sta_ds->htSupportedChannelWidthSet =
1670 (uint8_t) assoc_req->HTCaps.supportedChannelWidthSet;
1671 if (session->ch_width > CH_WIDTH_20MHZ &&
1672 session->ch_width <= CH_WIDTH_80P80MHZ &&
1673 sta_ds->htSupportedChannelWidthSet) {
1674 /*
1675 * peer just follows AP; so when we are softAP/GO,
1676 * we just store our session entry's secondary channel
1677 * offset here in peer INFRA STA. However, if peer's
1678 * 40MHz channel width support is disabled then
1679 * secondary channel will be zero
1680 */
1681 sta_ds->htSecondaryChannelOffset =
1682 session->htSecondaryChannelOffset;
1683 sta_ds->ch_width = CH_WIDTH_40MHZ;
1684 if (sta_ds->mlmStaContext.vhtCapability) {
1685 if (assoc_req->operMode.present) {
1686 sta_ds->ch_width =
1687 assoc_req->operMode.chanWidth;
1688 } else if (vht_caps->supportedChannelWidthSet ==
1689 VHT_CAP_160_AND_80P80_SUPP) {
1690 sta_ds->ch_width = CH_WIDTH_80P80MHZ;
1691 } else if (vht_caps->supportedChannelWidthSet ==
1692 VHT_CAP_160_SUPP) {
1693 if (vht_caps->vht_extended_nss_bw_cap &&
1694 vht_caps->extended_nss_bw_supp)
1695 sta_ds->ch_width =
1696 CH_WIDTH_80P80MHZ;
1697 else
1698 sta_ds->ch_width =
1699 CH_WIDTH_160MHZ;
1700 } else if (vht_caps->vht_extended_nss_bw_cap) {
1701 if (vht_caps->extended_nss_bw_supp ==
1702 VHT_EXTD_NSS_80_HALF_NSS_160)
1703 sta_ds->ch_width =
1704 CH_WIDTH_160MHZ;
1705 else if (vht_caps->extended_nss_bw_supp >
1706 VHT_EXTD_NSS_80_HALF_NSS_160)
1707 sta_ds->ch_width =
1708 CH_WIDTH_80P80MHZ;
1709 else
1710 sta_ds->ch_width =
1711 CH_WIDTH_80MHZ;
1712 } else {
1713 sta_ds->ch_width = CH_WIDTH_80MHZ;
1714 }
1715
1716 sta_ds->ch_width = QDF_MIN(sta_ds->ch_width,
1717 session->ch_width);
1718 }
1719 } else {
1720 sta_ds->htSupportedChannelWidthSet = 0;
1721 sta_ds->htSecondaryChannelOffset = 0;
1722 sta_ds->ch_width = CH_WIDTH_20MHZ;
1723 }
1724 sta_ds->htLdpcCapable =
1725 (uint8_t) assoc_req->HTCaps.advCodingCap;
1726 }
1727
1728 if (assoc_req->ExtCap.present)
1729 sta_ds->non_ecsa_capable =
1730 !((struct s_ext_cap *)assoc_req->ExtCap.bytes)->
1731 ext_chan_switch;
1732 else
1733 sta_ds->non_ecsa_capable = 1;
1734
1735 if (sta_ds->mlmStaContext.vhtCapability &&
1736 session->vhtCapability) {
1737 sta_ds->htMaxRxAMpduFactor =
1738 vht_caps->maxAMPDULenExp;
1739 sta_ds->vhtLdpcCapable =
1740 (uint8_t)vht_caps->ldpcCodingCap;
1741 if (session->vht_config.su_beam_formee &&
1742 vht_caps->suBeamFormerCap)
1743 sta_ds->vhtBeamFormerCapable = 1;
1744 else
1745 sta_ds->vhtBeamFormerCapable = 0;
1746 if (session->vht_config.su_beam_former &&
1747 vht_caps->suBeamformeeCap)
1748 sta_ds->vht_su_bfee_capable = 1;
1749 else
1750 sta_ds->vht_su_bfee_capable = 0;
1751
1752 pe_debug("peer_caps: suBformer: %d, suBformee: %d",
1753 vht_caps->suBeamFormerCap,
1754 vht_caps->suBeamformeeCap);
1755 pe_debug("self_cap: suBformer: %d, suBformee: %d",
1756 session->vht_config.su_beam_former,
1757 session->vht_config.su_beam_formee);
1758 pe_debug("connection's final cap: suBformer: %d, suBformee: %d",
1759 sta_ds->vhtBeamFormerCapable,
1760 sta_ds->vht_su_bfee_capable);
1761 }
1762
1763 sta_ds->vht_mcs_10_11_supp = 0;
1764 if (IS_DOT11_MODE_HT(session->dot11mode) &&
1765 sta_ds->mlmStaContext.vhtCapability) {
1766 if (mac_ctx->mlme_cfg->vht_caps.vht_cap_info.
1767 vht_mcs_10_11_supp &&
1768 assoc_req->qcn_ie.present &&
1769 assoc_req->qcn_ie.vht_mcs11_attr.present)
1770 sta_ds->vht_mcs_10_11_supp =
1771 assoc_req->qcn_ie.vht_mcs11_attr.
1772 vht_mcs_10_11_supp;
1773 }
1774 lim_intersect_sta_he_caps(mac_ctx, assoc_req, session, sta_ds);
1775
1776 lim_intersect_sta_eht_caps(mac_ctx, assoc_req, session, sta_ds);
1777
1778 lim_mlo_set_mld_mac_peer(sta_ds, assoc_req->mld_mac);
1779
1780 lim_mlo_save_mlo_info(sta_ds, &assoc_req->mlo_info);
1781
1782 if (lim_populate_matching_rate_set(mac_ctx, sta_ds,
1783 &(assoc_req->supportedRates),
1784 &(assoc_req->extendedRates),
1785 assoc_req->HTCaps.supportedMCSSet,
1786 session, vht_caps, &assoc_req->he_cap,
1787 &assoc_req->eht_cap) != QDF_STATUS_SUCCESS) {
1788 /* Could not update hash table entry at DPH with rateset */
1789 pe_err("Couldn't update hash entry for aid: %d MacAddr: "
1790 QDF_MAC_ADDR_FMT,
1791 peer_idx, QDF_MAC_ADDR_REF(sa));
1792
1793 /* Release AID */
1794 if (lim_is_mlo_conn(session, sta_ds)) {
1795 if (lim_is_mlo_recv_assoc(sta_ds))
1796 lim_release_mlo_conn_idx(mac_ctx, peer_idx,
1797 session, true);
1798 else
1799 lim_release_mlo_conn_idx(mac_ctx, peer_idx,
1800 session, false);
1801 } else {
1802 lim_release_peer_idx(mac_ctx, peer_idx, session);
1803 }
1804
1805 lim_reject_association(mac_ctx, sa, sub_type, true,
1806 auth_type, peer_idx, false,
1807 STATUS_UNSPECIFIED_FAILURE, session);
1808 pe_err("Delete dph hash entry");
1809 if (dph_delete_hash_entry(mac_ctx, sa, sta_ds->assocId,
1810 &session->dph.dphHashTable) !=
1811 QDF_STATUS_SUCCESS)
1812 pe_err("error deleting hash entry");
1813 return false;
1814 }
1815 if (assoc_req->operMode.present) {
1816 sta_ds->vhtSupportedRxNss = assoc_req->operMode.rxNSS + 1;
1817 } else {
1818 sta_ds->vhtSupportedRxNss =
1819 ((sta_ds->supportedRates.vhtTxMCSMap & MCSMAPMASK2x2)
1820 == MCSMAPMASK2x2) ? 1 : 2;
1821 }
1822 lim_update_stads_he_6ghz_op(session, sta_ds);
1823 lim_update_sta_ds_op_classes(assoc_req, sta_ds);
1824 lim_update_stads_eht_bw_320mhz(session, sta_ds);
1825
1826 /* Add STA context at MAC HW (BMU, RHP & TFP) */
1827 sta_ds->qosMode = false;
1828 sta_ds->lleEnabled = false;
1829 if (assoc_req->capabilityInfo.qos && (qos_mode == eHAL_SET)) {
1830 sta_ds->lleEnabled = true;
1831 sta_ds->qosMode = true;
1832 }
1833
1834 sta_ds->wmeEnabled = false;
1835 sta_ds->wsmEnabled = false;
1836 limGetWmeMode(session, &wme_mode);
1837 if ((!sta_ds->lleEnabled) && assoc_req->wmeInfoPresent
1838 && (wme_mode == eHAL_SET)) {
1839 sta_ds->wmeEnabled = true;
1840 sta_ds->qosMode = true;
1841 limGetWsmMode(session, &wsm_mode);
1842 /*
1843 * WMM_APSD - WMM_SA related processing should be separate;
1844 * WMM_SA and WMM_APSD can coexist
1845 */
1846 if (assoc_req->WMMInfoStation.present) {
1847 /* check whether AP supports or not */
1848 if (LIM_IS_AP_ROLE(session) &&
1849 (session->apUapsdEnable == 0) &&
1850 (assoc_req->WMMInfoStation.acbe_uapsd ||
1851 assoc_req->WMMInfoStation.acbk_uapsd ||
1852 assoc_req->WMMInfoStation.acvo_uapsd ||
1853 assoc_req->WMMInfoStation.acvi_uapsd)) {
1854 /*
1855 * Rcvd Re/Assoc Req from STA when UPASD is
1856 * not supported.
1857 */
1858 pe_err("UAPSD not supported, reply accordingly");
1859 /* update UAPSD and send it to LIM to add STA */
1860 sta_ds->qos.capability.qosInfo.acbe_uapsd = 0;
1861 sta_ds->qos.capability.qosInfo.acbk_uapsd = 0;
1862 sta_ds->qos.capability.qosInfo.acvo_uapsd = 0;
1863 sta_ds->qos.capability.qosInfo.acvi_uapsd = 0;
1864 sta_ds->qos.capability.qosInfo.maxSpLen = 0;
1865 } else {
1866 /* update UAPSD and send it to LIM to add STA */
1867 sta_ds->qos.capability.qosInfo.acbe_uapsd =
1868 assoc_req->WMMInfoStation.acbe_uapsd;
1869 sta_ds->qos.capability.qosInfo.acbk_uapsd =
1870 assoc_req->WMMInfoStation.acbk_uapsd;
1871 sta_ds->qos.capability.qosInfo.acvo_uapsd =
1872 assoc_req->WMMInfoStation.acvo_uapsd;
1873 sta_ds->qos.capability.qosInfo.acvi_uapsd =
1874 assoc_req->WMMInfoStation.acvi_uapsd;
1875 sta_ds->qos.capability.qosInfo.maxSpLen =
1876 assoc_req->WMMInfoStation.max_sp_length;
1877 }
1878 }
1879 if (assoc_req->wsmCapablePresent && (wsm_mode == eHAL_SET))
1880 sta_ds->wsmEnabled = true;
1881 }
1882 /* Re/Assoc Response frame to requesting STA */
1883 sta_ds->mlmStaContext.subType = sub_type;
1884
1885 sta_ds->rmfEnabled = (pmf_connection) ? 1 : 0;
1886 sta_ds->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS;
1887 timer_id.fields.sessionId = session->peSessionId;
1888 timer_id.fields.peerIdx = peer_idx;
1889 retry_interval = mac_ctx->mlme_cfg->gen.pmf_sa_query_retry_interval;
1890 if (cfg_min(CFG_PMF_SA_QUERY_RETRY_INTERVAL) > retry_interval) {
1891 retry_interval = cfg_default(CFG_PMF_SA_QUERY_RETRY_INTERVAL);
1892 }
1893 if (sta_ds->rmfEnabled) {
1894 sta_ds->ocv_enabled = lim_is_ocv_enable_in_assoc_req(mac_ctx,
1895 assoc_req);
1896 if (sta_ds->ocv_enabled)
1897 sta_ds->last_ocv_done_freq = session->curr_op_freq;
1898 /* Try to delete it before, creating.*/
1899 lim_delete_pmf_query_timer(sta_ds);
1900 if (tx_timer_create(mac_ctx, &sta_ds->pmfSaQueryTimer,
1901 "PMF SA Query timer", lim_pmf_sa_query_timer_handler,
1902 timer_id.value,
1903 SYS_MS_TO_TICKS((retry_interval * 1024) / 1000),
1904 0, TX_NO_ACTIVATE) != TX_SUCCESS) {
1905 pe_err("could not create PMF SA Query timer");
1906 lim_reject_association(mac_ctx, sa, sub_type,
1907 true, auth_type, peer_idx, false,
1908 STATUS_UNSPECIFIED_FAILURE,
1909 session);
1910 return false;
1911 }
1912 pe_debug("Created pmf timer assoc-id:%d sta mac" QDF_MAC_ADDR_FMT,
1913 sta_ds->assocId, QDF_MAC_ADDR_REF(sta_ds->staAddr));
1914 }
1915
1916 if (assoc_req->ExtCap.present) {
1917 lim_set_stads_rtt_cap(sta_ds,
1918 (struct s_ext_cap *) assoc_req->ExtCap.bytes, mac_ctx);
1919 } else {
1920 sta_ds->timingMeasCap = 0;
1921 pe_debug("ExtCap not present");
1922 }
1923 lim_ap_check_6g_compatible_peer(mac_ctx, session);
1924 return true;
1925 }
1926
1927 /**
1928 * lim_update_sta_ctx() - add/del sta depending on connection state machine
1929 * @mac_ctx: pointer to Global MAC structure
1930 * @session: pointer to pe session entry
1931 * @assoc_req: pointer to ASSOC/REASSOC Request frame
1932 * @sub_type: Assoc(=0) or Reassoc(=1) Requestframe
1933 * @sta_ds: station dph entry
1934 * @update_ctx: indicates if STA context already exist
1935 *
1936 * Checks for SSID match
1937 *
1938 * Return: true of no error, false otherwise
1939 */
lim_update_sta_ctx(struct mac_context * mac_ctx,struct pe_session * session,tpSirAssocReq assoc_req,uint8_t sub_type,tpDphHashNode sta_ds,uint8_t update_ctx)1940 static bool lim_update_sta_ctx(struct mac_context *mac_ctx, struct pe_session *session,
1941 tpSirAssocReq assoc_req, uint8_t sub_type,
1942 tpDphHashNode sta_ds, uint8_t update_ctx)
1943 {
1944 tLimMlmStates mlm_prev_state;
1945 /*
1946 * BTAMP: If STA context already exist (ie. update_ctx = 1) for this STA
1947 * then we should delete the old one, and add the new STA. This is taken
1948 * care of in the lim_del_sta() routine.
1949 *
1950 * Prior to BTAMP, we were setting this flag so that when PE receives
1951 * SME_ASSOC_CNF, and if this flag is set, then PE shall delete the old
1952 * station and then add. But now in BTAMP, we're directly adding station
1953 * before waiting for SME_ASSOC_CNF, so we can do this now.
1954 */
1955 if (!(update_ctx)) {
1956 sta_ds->mlmStaContext.updateContext = 0;
1957
1958 /*
1959 * BTAMP: Add STA context at HW - issue WMA_ADD_STA_REQ to HAL
1960 */
1961 if (lim_add_sta(mac_ctx, sta_ds, false, session) !=
1962 QDF_STATUS_SUCCESS) {
1963 pe_err("could not Add STA with assocId: %d",
1964 sta_ds->assocId);
1965 lim_reject_association(mac_ctx, sta_ds->staAddr,
1966 sta_ds->mlmStaContext.subType, true,
1967 sta_ds->mlmStaContext.authType,
1968 sta_ds->assocId, true,
1969 STATUS_UNSPECIFIED_FAILURE,
1970 session);
1971
1972 if (session->parsedAssocReq)
1973 assoc_req =
1974 session->parsedAssocReq[sta_ds->assocId];
1975 return false;
1976 }
1977 } else {
1978 sta_ds->mlmStaContext.updateContext = 1;
1979 mlm_prev_state = sta_ds->mlmStaContext.mlmState;
1980
1981 /*
1982 * As per the HAL/FW needs the reassoc req need not be calling
1983 * lim_del_sta
1984 */
1985 if (sub_type != LIM_REASSOC) {
1986 /*
1987 * we need to set the mlmState here in order
1988 * differentiate in lim_del_sta.
1989 */
1990 sta_ds->mlmStaContext.mlmState =
1991 eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE;
1992 if (lim_del_sta(mac_ctx, sta_ds, true, session)
1993 != QDF_STATUS_SUCCESS) {
1994 pe_err("Couldn't DEL STA, assocId: %d sta mac"
1995 QDF_MAC_ADDR_FMT, sta_ds->assocId,
1996 QDF_MAC_ADDR_REF(sta_ds->staAddr));
1997 lim_reject_association(mac_ctx, sta_ds->staAddr,
1998 sta_ds->mlmStaContext.subType, true,
1999 sta_ds->mlmStaContext.authType,
2000 sta_ds->assocId, true,
2001 STATUS_UNSPECIFIED_FAILURE,
2002 session);
2003
2004 /* Restoring the state back. */
2005 sta_ds->mlmStaContext.mlmState = mlm_prev_state;
2006 if (session->parsedAssocReq)
2007 assoc_req = session->parsedAssocReq[
2008 sta_ds->assocId];
2009 return false;
2010 }
2011 } else {
2012 /*
2013 * mlmState is changed in lim_add_sta context use the
2014 * same AID, already allocated
2015 */
2016 if (lim_add_sta(mac_ctx, sta_ds, false, session)
2017 != QDF_STATUS_SUCCESS) {
2018 pe_err("UPASD not supported, REASSOC Failed");
2019 lim_reject_association(mac_ctx, sta_ds->staAddr,
2020 sta_ds->mlmStaContext.subType, true,
2021 sta_ds->mlmStaContext.authType,
2022 sta_ds->assocId, true,
2023 STATUS_TDLS_WAKEUP_REJECT,
2024 session);
2025
2026 /* Restoring the state back. */
2027 sta_ds->mlmStaContext.mlmState = mlm_prev_state;
2028 if (session->parsedAssocReq)
2029 assoc_req = session->parsedAssocReq[
2030 sta_ds->assocId];
2031 return false;
2032 }
2033 }
2034 }
2035 return true;
2036 }
2037
lim_process_assoc_cleanup(struct mac_context * mac_ctx,struct pe_session * session,tpSirAssocReq assoc_req,tpDphHashNode sta_ds,bool assoc_req_copied)2038 void lim_process_assoc_cleanup(struct mac_context *mac_ctx,
2039 struct pe_session *session,
2040 tpSirAssocReq assoc_req,
2041 tpDphHashNode sta_ds,
2042 bool assoc_req_copied)
2043 {
2044 tpSirAssocReq tmp_assoc_req;
2045
2046 if (assoc_req) {
2047 lim_free_assoc_req_frm_buf(assoc_req);
2048
2049 qdf_mem_free(assoc_req);
2050 /* to avoid double free */
2051 if (assoc_req_copied && session->parsedAssocReq && sta_ds)
2052 session->parsedAssocReq[sta_ds->assocId] = NULL;
2053 }
2054
2055 /* If it is not duplicate Assoc request then only make to Null */
2056 if ((sta_ds) &&
2057 (sta_ds->mlmStaContext.mlmState != eLIM_MLM_WT_ADD_STA_RSP_STATE)) {
2058 if (session->parsedAssocReq) {
2059 tmp_assoc_req =
2060 session->parsedAssocReq[sta_ds->assocId];
2061 if (tmp_assoc_req) {
2062 lim_free_assoc_req_frm_buf(tmp_assoc_req);
2063 qdf_mem_free(tmp_assoc_req);
2064 session->parsedAssocReq[sta_ds->assocId] = NULL;
2065 }
2066 }
2067 }
2068 }
2069
2070 /**
2071 * lim_defer_sme_indication() - Defer assoc indication to SME
2072 * @mac_ctx: Pointer to Global MAC structure
2073 * @session: pe session entry
2074 * @sub_type: Indicates whether it is Association Request(=0) or Reassociation
2075 * Request(=1) frame
2076 * @sa: Mac address of requesting peer
2077 * @assoc_req: pointer to ASSOC/REASSOC Request frame
2078 * @pmf_connection: flag indicating pmf connection
2079 * @assoc_req_copied: boolean to indicate if assoc req was copied to tmp above
2080 * @dup_entry: flag indicating if duplicate entry found
2081 * @partner_peer_idx: association id allocated by partner peer
2082 *
2083 * Defer Initialization of PE data structures and wait for an external event.
2084 * lim_send_assoc_ind_to_sme() will be called to initialize PE data structures
2085 * when the expected event is received.
2086 *
2087 * Return: void
2088 */
lim_defer_sme_indication(struct mac_context * mac_ctx,struct pe_session * session,uint8_t sub_type,tSirMacAddr sa,struct sSirAssocReq * assoc_req,bool pmf_connection,bool assoc_req_copied,bool dup_entry,struct sDphHashNode * sta_ds,uint16_t partner_peer_idx)2089 static void lim_defer_sme_indication(struct mac_context *mac_ctx,
2090 struct pe_session *session,
2091 uint8_t sub_type,
2092 tSirMacAddr sa,
2093 struct sSirAssocReq *assoc_req,
2094 bool pmf_connection,
2095 bool assoc_req_copied,
2096 bool dup_entry,
2097 struct sDphHashNode *sta_ds,
2098 uint16_t partner_peer_idx)
2099 {
2100 struct tLimPreAuthNode *sta_pre_auth_ctx;
2101 struct lim_assoc_data *cached_req;
2102
2103 /* Extract pre-auth context for the STA, if any. */
2104 sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx, sa);
2105 if (sta_pre_auth_ctx->assoc_req.present) {
2106 pe_debug("Free the cached assoc req as a new one is received");
2107 cached_req = &sta_pre_auth_ctx->assoc_req;
2108 lim_process_assoc_cleanup(mac_ctx, session,
2109 cached_req->assoc_req,
2110 cached_req->sta_ds,
2111 cached_req->assoc_req_copied);
2112 }
2113
2114 sta_pre_auth_ctx->assoc_req.present = true;
2115 sta_pre_auth_ctx->assoc_req.sub_type = sub_type;
2116 qdf_mem_copy(sta_pre_auth_ctx->assoc_req.sa, sa,
2117 sizeof(sta_pre_auth_ctx->assoc_req.sa));
2118 sta_pre_auth_ctx->assoc_req.assoc_req = assoc_req;
2119 sta_pre_auth_ctx->assoc_req.pmf_connection = pmf_connection;
2120 sta_pre_auth_ctx->assoc_req.assoc_req_copied = assoc_req_copied;
2121 sta_pre_auth_ctx->assoc_req.dup_entry = dup_entry;
2122 sta_pre_auth_ctx->assoc_req.sta_ds = sta_ds;
2123 sta_pre_auth_ctx->assoc_req.partner_peer_idx = partner_peer_idx;
2124 }
2125
lim_is_sae_akm_present(tDot11fIERSN * const rsn_ie)2126 static bool lim_is_sae_akm_present(tDot11fIERSN * const rsn_ie)
2127 {
2128 uint16_t i;
2129
2130 if (rsn_ie->akm_suite_cnt > 6)
2131 return false;
2132
2133 for (i = 0; i < rsn_ie->akm_suite_cnt; i++) {
2134 if ((LE_READ_4(rsn_ie->akm_suite[i]) == RSN_AUTH_KEY_MGMT_SAE) ||
2135 (LE_READ_4(rsn_ie->akm_suite[i]) ==
2136 RSN_AUTH_KEY_MGMT_SAE_EXT_KEY)) {
2137 pe_debug("SAE AKM present");
2138 return true;
2139 }
2140 }
2141 return false;
2142 }
2143
lim_is_pmkid_found_for_peer(struct mac_context * mac_ctx,tSirMacAddr peer_mac_addr,struct pe_session * session,uint8_t * pmkid,uint16_t pmkid_count)2144 static bool lim_is_pmkid_found_for_peer(struct mac_context *mac_ctx,
2145 tSirMacAddr peer_mac_addr,
2146 struct pe_session *session,
2147 uint8_t *pmkid,
2148 uint16_t pmkid_count)
2149 {
2150 uint32_t i;
2151 uint8_t *session_pmkid;
2152 struct wlan_crypto_pmksa *pmkid_cache;
2153
2154 pmkid_cache = qdf_mem_malloc(sizeof(*pmkid_cache));
2155
2156 if (!pmkid_cache)
2157 return false;
2158
2159 qdf_mem_copy(pmkid_cache->bssid.bytes, peer_mac_addr,
2160 QDF_MAC_ADDR_SIZE);
2161
2162 if (!cm_lookup_pmkid_using_bssid(mac_ctx->psoc, session->vdev_id,
2163 pmkid_cache)) {
2164 qdf_mem_free(pmkid_cache);
2165 return false;
2166 }
2167
2168 session_pmkid = pmkid_cache->pmkid;
2169 for (i = 0; i < pmkid_count; i++) {
2170 if (!qdf_mem_cmp(pmkid + (i * PMKID_LEN),
2171 session_pmkid, PMKID_LEN)) {
2172 qdf_mem_free(pmkid_cache);
2173 return true;
2174 }
2175 }
2176
2177 pe_debug("PMKID in cache doesn't match with PMKIDs from the peer");
2178 qdf_mem_free(pmkid_cache);
2179
2180 return false;
2181 }
2182
lim_is_sae_peer_allowed(struct mac_context * mac_ctx,struct pe_session * session,tDot11fIERSN * rsn_ie,tSirMacAddr sa,enum wlan_status_code * mac_status_code)2183 static bool lim_is_sae_peer_allowed(struct mac_context *mac_ctx,
2184 struct pe_session *session,
2185 tDot11fIERSN *rsn_ie, tSirMacAddr sa,
2186 enum wlan_status_code *mac_status_code)
2187 {
2188 bool is_allowed = false;
2189 uint8_t *peer_mac_addr = sa;
2190
2191 /* Allow the peer with valid PMKID */
2192 if (!rsn_ie->pmkid_count) {
2193 *mac_status_code = STATUS_NOT_SUPPORTED_AUTH_ALG;
2194 pe_debug("No PMKID present in RSNIE; Tried to use SAE AKM after non-SAE authentication");
2195 } else if (lim_is_pmkid_found_for_peer(mac_ctx, peer_mac_addr, session,
2196 &rsn_ie->pmkid[0][0],
2197 rsn_ie->pmkid_count)) {
2198 pe_debug("Valid PMKID found for SAE peer");
2199 is_allowed = true;
2200 } else {
2201 *mac_status_code = STATUS_INVALID_PMKID;
2202 pe_debug("No valid PMKID found for SAE peer");
2203 }
2204
2205 return is_allowed;
2206 }
2207
lim_validate_pmkid_for_sae(struct mac_context * mac_ctx,struct pe_session * session,tpSirAssocReq assoc_req,tSirMacAddr sa,uint8_t sub_type)2208 static bool lim_validate_pmkid_for_sae(struct mac_context *mac_ctx,
2209 struct pe_session *session,
2210 tpSirAssocReq assoc_req, tSirMacAddr sa,
2211 uint8_t sub_type)
2212 {
2213 tDot11fIERSN rsn_ie = {0};
2214 enum wlan_status_code code = STATUS_INVALID_IE;
2215
2216 if (!assoc_req->rsnPresent)
2217 return true;
2218
2219 if (dot11f_unpack_ie_rsn(mac_ctx, &assoc_req->rsn.info[0],
2220 assoc_req->rsn.length,
2221 &rsn_ie, false) != DOT11F_PARSE_SUCCESS)
2222 goto reject_assoc;
2223
2224 if (lim_is_sae_akm_present(&rsn_ie) &&
2225 !assoc_req->is_sae_authenticated &&
2226 !lim_is_sae_peer_allowed(mac_ctx, session, &rsn_ie, sa, &code))
2227 goto reject_assoc;
2228
2229 return true;
2230
2231 reject_assoc:
2232 lim_send_assoc_rsp_mgmt_frame(mac_ctx, code, 1, sa, sub_type, 0,
2233 session, false);
2234 return false;
2235 }
2236
lim_send_assoc_ind_to_sme(struct mac_context * mac_ctx,struct pe_session * session,uint8_t sub_type,tSirMacAddr sa,tpSirAssocReq assoc_req,enum ani_akm_type akm_type,bool pmf_connection,bool * assoc_req_copied,bool dup_entry,bool force_1x1,uint16_t partner_peer_idx)2237 bool lim_send_assoc_ind_to_sme(struct mac_context *mac_ctx,
2238 struct pe_session *session,
2239 uint8_t sub_type, tSirMacAddr sa,
2240 tpSirAssocReq assoc_req,
2241 enum ani_akm_type akm_type,
2242 bool pmf_connection, bool *assoc_req_copied,
2243 bool dup_entry, bool force_1x1,
2244 uint16_t partner_peer_idx)
2245 {
2246 uint16_t peer_idx;
2247 struct tLimPreAuthNode *sta_pre_auth_ctx;
2248 tpDphHashNode sta_ds = NULL;
2249 tHalBitVal qos_mode;
2250 tAniAuthType auth_type;
2251 uint8_t update_ctx = false;
2252
2253 limGetQosMode(session, &qos_mode);
2254 /* Extract 'associated' context for STA, if any. */
2255 sta_ds = dph_lookup_hash_entry(mac_ctx, sa, &peer_idx,
2256 &session->dph.dphHashTable);
2257
2258 /* Extract pre-auth context for the STA, if any. */
2259 sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx, sa);
2260
2261 if (!sta_ds) {
2262 if (!lim_process_assoc_req_no_sta_ctx(mac_ctx, sa, session,
2263 assoc_req, sub_type,
2264 sta_pre_auth_ctx, sta_ds,
2265 &auth_type,
2266 partner_peer_idx))
2267 return false;
2268 } else {
2269 if (!lim_process_assoc_req_sta_ctx(mac_ctx, sa, session,
2270 assoc_req, sub_type,
2271 sta_pre_auth_ctx, sta_ds,
2272 peer_idx, &auth_type,
2273 &update_ctx))
2274 return false;
2275 goto send_ind_to_sme;
2276 }
2277
2278 if (LIM_IS_AP_ROLE(session)) {
2279 if ((assoc_req->wpaPresent || assoc_req->rsnPresent) &&
2280 !session->privacy) {
2281 pe_debug("reject assoc. wpa: %d, rsn: %d, privacy: %d",
2282 assoc_req->wpaPresent,
2283 assoc_req->rsnPresent,
2284 session->privacy);
2285 lim_reject_association(mac_ctx, sa, sub_type, true,
2286 auth_type, peer_idx, false,
2287 STATUS_UNSPECIFIED_FAILURE,
2288 session);
2289 return false;
2290 }
2291 }
2292
2293 /* check if sta is allowed per QoS AC rules */
2294 if (!lim_chk_wmm(mac_ctx, sa, session, assoc_req, sub_type, qos_mode))
2295 return false;
2296
2297 if (!lim_validate_pmkid_for_sae(mac_ctx, session, assoc_req,
2298 sa, sub_type))
2299 return false;
2300
2301 /* STA is Associated ! */
2302 pe_debug("Received: %s Req successful from " QDF_MAC_ADDR_FMT,
2303 (sub_type == LIM_ASSOC) ? "Assoc" : "ReAssoc",
2304 QDF_MAC_ADDR_REF(sa));
2305
2306 /*
2307 * AID for this association will be same as the peer Index used in DPH
2308 * table. Assign unused/least recently used peer Index from perStaDs.
2309 * NOTE: lim_assign_peer_idx() assigns AID values ranging between
2310 * 1 - cfg_item(WNI_CFG_ASSOC_STA_LIMIT)
2311 */
2312
2313 if (wlan_vdev_mlme_is_mlo_ap(session->vdev) &&
2314 assoc_req->eht_cap.present &&
2315 IS_DOT11_MODE_EHT(session->dot11mode) &&
2316 (partner_peer_idx ||
2317 !qdf_is_macaddr_zero((struct qdf_mac_addr *)assoc_req->mld_mac)))
2318 peer_idx = lim_assign_mlo_conn_idx(mac_ctx, session,
2319 partner_peer_idx);
2320 else
2321 peer_idx = lim_assign_peer_idx(mac_ctx, session);
2322
2323 if (!peer_idx && !partner_peer_idx) {
2324 /* Could not assign AID. Reject association */
2325 pe_err("PeerIdx not available. Reject associaton");
2326 lim_reject_association(mac_ctx, sa, sub_type,
2327 true, auth_type, peer_idx, false,
2328 STATUS_UNSPECIFIED_FAILURE,
2329 session);
2330 return false;
2331 } else if (!peer_idx) {
2332 pe_err("mlo partner PeerIdx not available. Reject associaton");
2333 lim_send_sme_max_assoc_exceeded_ntf(mac_ctx, sa,
2334 session->smeSessionId);
2335 return false;
2336 }
2337
2338 /* Add an entry to hash table maintained by DPH module */
2339
2340 sta_ds = dph_add_hash_entry(mac_ctx, sa, peer_idx,
2341 &session->dph.dphHashTable);
2342
2343 if (!sta_ds && !partner_peer_idx) {
2344 /* Could not add hash table entry at DPH */
2345 pe_err("couldn't add hash entry at DPH for aid: %d MacAddr:"
2346 QDF_MAC_ADDR_FMT, peer_idx, QDF_MAC_ADDR_REF(sa));
2347
2348 /* Release AID */
2349 if (wlan_vdev_mlme_is_mlo_ap(session->vdev) &&
2350 assoc_req->eht_cap.present &&
2351 IS_DOT11_MODE_EHT(session->dot11mode) &&
2352 (partner_peer_idx || assoc_req->mlo_info.num_partner_links))
2353 lim_release_mlo_conn_idx(mac_ctx, peer_idx, session,
2354 true);
2355 else
2356 lim_release_peer_idx(mac_ctx, peer_idx, session);
2357
2358 lim_reject_association(mac_ctx, sa, sub_type,
2359 true, auth_type, peer_idx, false,
2360 STATUS_UNSPECIFIED_FAILURE,
2361 session);
2362 return false;
2363 } else if (!sta_ds) {
2364 pe_err("mlo partner peer couldn't add hash entry at DPH for aid: %d MacAddr:"
2365 QDF_MAC_ADDR_FMT, peer_idx, QDF_MAC_ADDR_REF(sa));
2366 lim_send_sme_max_assoc_exceeded_ntf(mac_ctx, sa,
2367 session->smeSessionId);
2368 return false;
2369 }
2370
2371 /*only mlo partner peer get valid aid before proc assoc req*/
2372 if (!partner_peer_idx)
2373 lim_set_mlo_recv_assoc(sta_ds, true);
2374 else
2375 lim_set_mlo_recv_assoc(sta_ds, false);
2376
2377 send_ind_to_sme:
2378 if (!lim_update_sta_ds(mac_ctx, sa, session, assoc_req,
2379 sub_type, sta_ds, auth_type, akm_type,
2380 assoc_req_copied, peer_idx, qos_mode,
2381 pmf_connection, force_1x1))
2382 return false;
2383
2384 /* BTAMP: Storing the parsed assoc request in the session array */
2385 if (session->parsedAssocReq)
2386 session->parsedAssocReq[sta_ds->assocId] = assoc_req;
2387 *assoc_req_copied = true;
2388
2389 /* If it is duplicate entry wait till the peer is deleted */
2390 if (!dup_entry) {
2391 if (!lim_update_sta_ctx(mac_ctx, session, assoc_req,
2392 sub_type, sta_ds, update_ctx))
2393 return false;
2394 }
2395
2396 /* AddSta is success here */
2397 if (LIM_IS_AP_ROLE(session) && IS_DOT11_MODE_HT(session->dot11mode) &&
2398 assoc_req->HTCaps.present && assoc_req->wmeInfoPresent) {
2399 /*
2400 * Update in the HAL Sta Table for the Update of the Protection
2401 * Mode
2402 */
2403 lim_post_sm_state_update(mac_ctx,
2404 sta_ds->htMIMOPSState, sta_ds->staAddr,
2405 session->smeSessionId);
2406 }
2407
2408 return true;
2409 }
2410
2411 /**
2412 * lim_peer_present_on_any_sta() - Check if Same MAC is connected with STA, i.e.
2413 * duplicate mac detection.
2414 * @mac_ctx: Pointer to Global MAC structure
2415 * @peer_addr: peer address to check
2416 *
2417 * This function will return true if a peer STA and AP are using same mac
2418 * address.
2419 *
2420 * @Return: bool
2421 */
2422 static bool
lim_peer_present_on_any_sta(struct mac_context * mac_ctx,uint8_t * peer_addr)2423 lim_peer_present_on_any_sta(struct mac_context *mac_ctx, uint8_t *peer_addr)
2424 {
2425 struct wlan_objmgr_peer *peer;
2426 bool sta_peer_present = false;
2427 enum QDF_OPMODE mode;
2428 uint8_t peer_vdev_id;
2429
2430 peer = wlan_objmgr_get_peer_by_mac(mac_ctx->psoc, peer_addr,
2431 WLAN_LEGACY_MAC_ID);
2432 if (!peer)
2433 return sta_peer_present;
2434
2435 peer_vdev_id = wlan_vdev_get_id(wlan_peer_get_vdev(peer));
2436 mode = wlan_vdev_mlme_get_opmode(wlan_peer_get_vdev(peer));
2437 if (mode == QDF_STA_MODE || mode == QDF_P2P_CLIENT_MODE) {
2438 pe_debug("duplicate mac detected!!! Peer " QDF_MAC_ADDR_FMT " present on STA vdev %d",
2439 QDF_MAC_ADDR_REF(peer_addr), peer_vdev_id);
2440 sta_peer_present = true;
2441 }
2442
2443 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
2444
2445 return sta_peer_present;
2446 }
2447
lim_check_assoc_req(struct mac_context * mac_ctx,uint8_t sub_type,tSirMacAddr sa,struct pe_session * session)2448 QDF_STATUS lim_check_assoc_req(struct mac_context *mac_ctx,
2449 uint8_t sub_type, tSirMacAddr sa,
2450 struct pe_session *session)
2451 {
2452 if (LIM_IS_STA_ROLE(session)) {
2453 pe_err("Rcvd unexpected ASSOC REQ, sessionid: %d sys sub_type: %d for role: %d from: "
2454 QDF_MAC_ADDR_FMT,
2455 session->peSessionId, sub_type,
2456 GET_LIM_SYSTEM_ROLE(session),
2457 QDF_MAC_ADDR_REF(sa));
2458 return QDF_STATUS_E_INVAL;
2459 }
2460
2461 if (session->limMlmState == eLIM_MLM_WT_DEL_BSS_RSP_STATE) {
2462 pe_err("drop ASSOC REQ on sessionid: %d role: %d from: "
2463 QDF_MAC_ADDR_FMT " in limMlmState: %d",
2464 session->peSessionId,
2465 GET_LIM_SYSTEM_ROLE(session),
2466 QDF_MAC_ADDR_REF(sa),
2467 eLIM_MLM_WT_DEL_BSS_RSP_STATE);
2468 return QDF_STATUS_E_INVAL;
2469 }
2470
2471 if (lim_peer_present_on_any_sta(mac_ctx, sa))
2472 /*
2473 * This mean a AP and STA have same mac address and device STA
2474 * is already connected to the AP, and STA is now trying to
2475 * connect to device SAP. So ignore association.
2476 */
2477 return QDF_STATUS_E_INVAL;
2478
2479 return QDF_STATUS_SUCCESS;
2480 }
2481
2482 #ifdef WLAN_SUPPORT_TWT
2483 /* lim_set_sap_peer_twt_cap() - Set SAP peer twt requestor and responder bit
2484 * @session: PE session handle
2485 * @ext_cap: pointer to ext cap
2486 *
2487 * This function is used to update SAP peer twt requestor and responder bit
2488 * from ext cap of assoc request received by SAP
2489 *
2490 * Return: None
2491 */
lim_set_sap_peer_twt_cap(struct pe_session * session,struct s_ext_cap * ext_cap)2492 static void lim_set_sap_peer_twt_cap(struct pe_session *session,
2493 struct s_ext_cap *ext_cap)
2494 {
2495 session->peer_twt_requestor = ext_cap->twt_requestor_support;
2496 session->peer_twt_responder = ext_cap->twt_responder_support;
2497
2498 pe_debug("Ext Cap peer TWT requestor: %d, responder: %d",
2499 ext_cap->twt_requestor_support,
2500 ext_cap->twt_responder_support);
2501 }
2502 #else
2503 static inline void
lim_set_sap_peer_twt_cap(struct pe_session * session,struct s_ext_cap * ext_cap)2504 lim_set_sap_peer_twt_cap(struct pe_session *session,
2505 struct s_ext_cap *ext_cap)
2506 {
2507 }
2508 #endif
2509
2510 /* lim_update_ap_ext_cap() - Update SAP with ext capabilities
2511 * @session: PE session handle
2512 * @ assoc_req: pointer to assoc req
2513 *
2514 * This function is called by lim_proc_assoc_req_frm_cmn to
2515 * update SAP ext capabilities
2516 *
2517 * Return: None
2518 */
lim_update_ap_ext_cap(struct pe_session * session,tpSirAssocReq assoc_req)2519 static void lim_update_ap_ext_cap(struct pe_session *session,
2520 tpSirAssocReq assoc_req)
2521 {
2522 struct s_ext_cap *ext_cap;
2523
2524 ext_cap = (struct s_ext_cap *)assoc_req->ExtCap.bytes;
2525 lim_set_sap_peer_twt_cap(session, ext_cap);
2526 }
2527
lim_proc_assoc_req_frm_cmn(struct mac_context * mac_ctx,uint8_t sub_type,struct pe_session * session,tSirMacAddr sa,tpSirAssocReq assoc_req,uint16_t peer_aid)2528 QDF_STATUS lim_proc_assoc_req_frm_cmn(struct mac_context *mac_ctx,
2529 uint8_t sub_type,
2530 struct pe_session *session,
2531 tSirMacAddr sa,
2532 tpSirAssocReq assoc_req,
2533 uint16_t peer_aid)
2534 {
2535 bool pmf_connection = false, assoc_req_copied = false;
2536 uint32_t phy_mode;
2537 tHalBitVal qos_mode;
2538 struct tLimPreAuthNode *sta_pre_auth_ctx;
2539 enum ani_akm_type akm_type = ANI_AKM_TYPE_NONE;
2540 tSirMacCapabilityInfo local_cap;
2541 tpDphHashNode sta_ds = NULL;
2542 bool dup_entry = false, force_1x1 = false;
2543 QDF_STATUS status;
2544 uint8_t *frm_body;
2545 uint32_t frame_len;
2546
2547 frm_body = assoc_req->assocReqFrame;
2548 frame_len = assoc_req->assocReqFrameLength;
2549 lim_get_phy_mode(mac_ctx, &phy_mode, session);
2550 limGetQosMode(session, &qos_mode);
2551
2552 status = lim_check_sta_in_pe_entries(mac_ctx, sa,
2553 session->peSessionId,
2554 &dup_entry);
2555 if (QDF_IS_STATUS_ERROR(status)) {
2556 pe_err("Reject assoc as duplicate entry is present and is already being deleted, assoc will be accepted once deletion is completed");
2557 /*
2558 * This mean that the duplicate entry is present on other vdev
2559 * and is already being deleted, so reject the assoc and lets
2560 * peer try again to connect, once peer is deleted from
2561 * other vdev.
2562 */
2563 if (!peer_aid)
2564 lim_send_assoc_rsp_mgmt_frame(
2565 mac_ctx,
2566 STATUS_UNSPECIFIED_FAILURE,
2567 1, sa,
2568 sub_type, 0, session, false);
2569 goto error;
2570 }
2571 /* check for the presence of vendor IE */
2572 if (session->access_policy_vendor_ie &&
2573 session->access_policy ==
2574 LIM_ACCESS_POLICY_RESPOND_IF_IE_IS_PRESENT) {
2575 if (frame_len <= LIM_ASSOC_REQ_IE_OFFSET) {
2576 pe_debug("Received action frame of invalid len %d",
2577 frame_len);
2578 goto error;
2579 }
2580 if (!wlan_get_vendor_ie_ptr_from_oui(
2581 &session->access_policy_vendor_ie[2],
2582 3, frm_body + LIM_ASSOC_REQ_IE_OFFSET,
2583 frame_len - LIM_ASSOC_REQ_IE_OFFSET)) {
2584 pe_err("Vendor ie not present and access policy is %x, Rejected association",
2585 session->access_policy);
2586 if (!peer_aid)
2587 lim_send_assoc_rsp_mgmt_frame(
2588 mac_ctx, STATUS_UNSPECIFIED_FAILURE,
2589 1, sa, sub_type, 0, session, false);
2590 goto error;
2591 }
2592 }
2593
2594 if (!lim_chk_assoc_req_parse_error(mac_ctx, sa, session,
2595 assoc_req, sub_type,
2596 frm_body, frame_len))
2597 goto error;
2598
2599 if (!lim_chk_capab(mac_ctx, sa, session, assoc_req,
2600 sub_type, &local_cap))
2601 goto error;
2602
2603 if (!lim_chk_ssid(mac_ctx, sa, session, assoc_req, sub_type))
2604 goto error;
2605
2606 if (!lim_chk_rates(mac_ctx, sa, session, assoc_req, sub_type))
2607 goto error;
2608
2609 if (!lim_chk_11g_only(mac_ctx, sa, session, assoc_req,
2610 sub_type))
2611 goto error;
2612
2613 if (!lim_chk_11n_only(mac_ctx, sa, session, assoc_req,
2614 sub_type))
2615 goto error;
2616
2617 if (!lim_chk_11ac_only(mac_ctx, sa, session, assoc_req,
2618 sub_type))
2619 goto error;
2620
2621 if (!lim_chk_11ax_only(mac_ctx, sa, session, assoc_req,
2622 sub_type))
2623 goto error;
2624
2625 if (!lim_chk_11be_only(mac_ctx, sa, session, assoc_req,
2626 sub_type))
2627 goto error;
2628
2629 if (!lim_check_11ax_basic_mcs(mac_ctx, sa, session, assoc_req,
2630 sub_type))
2631 goto error;
2632
2633 /* Spectrum Management (11h) specific checks */
2634 lim_process_for_spectrum_mgmt(mac_ctx, sa, session,
2635 assoc_req, sub_type, local_cap);
2636
2637 if (!lim_chk_mcs(mac_ctx, sa, session, assoc_req, sub_type))
2638 goto error;
2639
2640 if (!lim_chk_is_11b_sta_supported(mac_ctx, sa, session,
2641 assoc_req, sub_type, phy_mode))
2642 goto error;
2643
2644 /*
2645 * Check for 802.11n HT caps compatibility; are HT Capabilities
2646 * turned on in lim?
2647 */
2648 lim_print_ht_cap(mac_ctx, session, assoc_req);
2649
2650 if (!lim_chk_n_process_wpa_rsn_ie(mac_ctx, sa, session,
2651 assoc_req, sub_type,
2652 &pmf_connection,
2653 &akm_type))
2654 goto error;
2655
2656 /* Update ap ext cap */
2657 lim_update_ap_ext_cap(session, assoc_req);
2658
2659 /* Extract pre-auth context for the STA, if any. */
2660 sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx, sa);
2661
2662 /* SAE authentication is offloaded to hostapd. Hostapd sends
2663 * authentication status to driver after completing SAE
2664 * authentication (after sending out 4/4 SAE auth frame).
2665 * There is a possible race condition where driver gets
2666 * assoc request from SAE station before getting authentication
2667 * status from hostapd. Don't reject the association in such
2668 * cases and defer the processing of assoc request frame by caching
2669 * the frame and process it when the auth status is received.
2670 */
2671 if (sta_pre_auth_ctx &&
2672 sta_pre_auth_ctx->authType == eSIR_AUTH_TYPE_SAE &&
2673 sta_pre_auth_ctx->mlmState == eLIM_MLM_WT_SAE_AUTH_STATE) {
2674 pe_debug("Received assoc request frame while SAE authentication is in progress; Defer association request handling till SAE auth status is received");
2675 lim_defer_sme_indication(mac_ctx, session, sub_type, sa,
2676 assoc_req, pmf_connection,
2677 assoc_req_copied, dup_entry, sta_ds,
2678 peer_aid);
2679
2680 return QDF_STATUS_SUCCESS;
2681 }
2682
2683 if (session->opmode == QDF_P2P_GO_MODE) {
2684 /*
2685 * WAR: In P2P GO mode, if the P2P client device
2686 * is only HT capable and not VHT capable, but the P2P
2687 * GO device is VHT capable and advertises 2x2 NSS with
2688 * HT capability client device, which results in IOT
2689 * issues.
2690 * When GO is operating in DBS mode, GO beacons
2691 * advertise 2x2 capability but include OMN IE to
2692 * indicate current operating mode of 1x1. But here
2693 * peer device is only HT capable and will not
2694 * understand OMN IE.
2695 */
2696 force_1x1 = wlan_p2p_check_oui_and_force_1x1(
2697 frm_body + LIM_ASSOC_REQ_IE_OFFSET,
2698 frame_len - LIM_ASSOC_REQ_IE_OFFSET);
2699 }
2700
2701 /* Send assoc indication to SME */
2702 if (!lim_send_assoc_ind_to_sme(mac_ctx, session, sub_type, sa,
2703 assoc_req, akm_type, pmf_connection,
2704 &assoc_req_copied, dup_entry, force_1x1,
2705 peer_aid))
2706 goto error;
2707
2708 return QDF_STATUS_SUCCESS;
2709
2710 error:
2711 lim_process_assoc_cleanup(mac_ctx, session, assoc_req, sta_ds,
2712 assoc_req_copied);
2713
2714 return QDF_STATUS_E_FAILURE;
2715 }
2716
2717 /**
2718 * lim_process_assoc_req_frame() - Process RE/ASSOC Request frame.
2719 * @mac_ctx: Pointer to Global MAC structure
2720 * @rx_pkt_info: A pointer to Buffer descriptor + associated PDUs
2721 * @sub_type: Indicates whether it is Association Request(=0) or Reassociation
2722 * Request(=1) frame
2723 * @session: pe session entry
2724 *
2725 * This function is called to process RE/ASSOC Request frame.
2726 *
2727 * @Return: void
2728 */
lim_process_assoc_req_frame(struct mac_context * mac_ctx,uint8_t * rx_pkt_info,uint8_t sub_type,struct pe_session * session)2729 void lim_process_assoc_req_frame(struct mac_context *mac_ctx,
2730 uint8_t *rx_pkt_info,
2731 uint8_t sub_type,
2732 struct pe_session *session)
2733 {
2734 uint8_t *frm_body;
2735 uint16_t assoc_id = 0;
2736 uint32_t frame_len;
2737 tpSirMacMgmtHdr hdr;
2738 tpDphHashNode sta_ds = NULL;
2739 struct wlan_objmgr_vdev *vdev;
2740 tpSirAssocReq assoc_req;
2741
2742 hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
2743 frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
2744
2745 pe_nofl_rl_debug("Assoc req RX: subtype %d vdev %d sys role %d lim state %d rssi %d from " QDF_MAC_ADDR_FMT,
2746 sub_type, session->vdev_id, GET_LIM_SYSTEM_ROLE(session),
2747 session->limMlmState,
2748 WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info),
2749 QDF_MAC_ADDR_REF(hdr->sa));
2750
2751 if (QDF_IS_STATUS_ERROR(lim_check_assoc_req(mac_ctx, sub_type,
2752 hdr->sa, session)))
2753 return;
2754
2755 vdev = session->vdev;
2756 if (!vdev) {
2757 pe_err("vdev is NULL");
2758 return;
2759 }
2760
2761 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_UP ||
2762 wlan_vdev_mlme_get_substate(vdev) != WLAN_VDEV_SS_UP_ACTIVE) {
2763 pe_err("SAP is not up, drop ASSOC REQ on sessionid: %d",
2764 session->peSessionId);
2765
2766 return;
2767 }
2768
2769 /*
2770 * If a STA is already present in DPH and it is initiating a Assoc
2771 * re-transmit, do not process it. This can happen when first Assoc Req
2772 * frame is received but ACK lost at STA side. The ACK for this dropped
2773 * Assoc Req frame should be sent by HW. Host simply does not process it
2774 * once the entry for the STA is already present in DPH.
2775 */
2776 sta_ds = dph_lookup_hash_entry(mac_ctx, hdr->sa, &assoc_id,
2777 &session->dph.dphHashTable);
2778 if (sta_ds && !sta_ds->rmfEnabled) {
2779 /*
2780 * Drop only retries for non-PMF assoc requests.
2781 * For PMF case:
2782 * a) Before key installation - Drop assoc request
2783 * b) After key installation - Send SA query
2784 */
2785 if (hdr->fc.retry > 0) {
2786 pe_err("STA is initiating Assoc Req after ACK lost. Do not process sessionid: %d sys sub_type=%d for role=%d from: "
2787 QDF_MAC_ADDR_FMT, session->peSessionId,
2788 sub_type, GET_LIM_SYSTEM_ROLE(session),
2789 QDF_MAC_ADDR_REF(hdr->sa));
2790 return;
2791 } else if (sub_type == LIM_REASSOC) {
2792 /*
2793 * SAP should send reassoc response with reject code
2794 * to avoid IOT issues. as per the specification SAP
2795 * should do 4-way handshake after reassoc response and
2796 * some STA doesn't like 4way handshake after reassoc
2797 * where some STA does expect 4-way handshake.
2798 */
2799 lim_send_assoc_rsp_mgmt_frame(
2800 mac_ctx, STATUS_ASSOC_DENIED_UNSPEC,
2801 sta_ds->assocId, sta_ds->staAddr,
2802 sub_type, sta_ds, session, false);
2803 pe_err("Rejecting reassoc req from STA");
2804 return;
2805 } else {
2806 /*
2807 * Do this only for non PMF case.
2808 * STA might have missed the assoc response, so it is
2809 * sending assoc request frame again.
2810 */
2811 lim_send_assoc_rsp_mgmt_frame(
2812 mac_ctx, QDF_STATUS_SUCCESS,
2813 sta_ds->assocId, sta_ds->staAddr,
2814 sub_type,
2815 sta_ds, session, false);
2816 pe_err("DUT already received an assoc request frame and STA is sending another assoc req.So, do not Process sessionid: %d sys sub_type: %d for role: %d from: "
2817 QDF_MAC_ADDR_FMT,
2818 session->peSessionId, sub_type,
2819 session->limSystemRole,
2820 QDF_MAC_ADDR_REF(hdr->sa));
2821 return;
2822 }
2823 } else if (sta_ds && sta_ds->rmfEnabled && !sta_ds->is_key_installed) {
2824 /* When PMF enabled, SA Query will be triggered
2825 * unexpectedly if duplicated assoc_req received -
2826 * 1) after pre_auth node deleted and
2827 * 2) before key installed.
2828 * Here drop such duplicated assoc_req frame.
2829 */
2830 pe_err("Drop duplicate assoc_req before 4-way HS");
2831 return;
2832 }
2833
2834 /* Get pointer to Re/Association Request frame body */
2835 frm_body = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
2836
2837 if (IEEE80211_IS_MULTICAST(hdr->sa)) {
2838 /*
2839 * Rcvd Re/Assoc Req frame from BC/MC address Log error and
2840 * ignore it
2841 */
2842 pe_err("Rcvd: %s Req, sessionid: %d from a BC/MC address"
2843 QDF_MAC_ADDR_FMT,
2844 (LIM_ASSOC == sub_type) ? "Assoc" : "ReAssoc",
2845 session->peSessionId, QDF_MAC_ADDR_REF(hdr->sa));
2846 return;
2847 }
2848
2849 if (false == lim_chk_sa_da(mac_ctx, hdr, session, sub_type))
2850 return;
2851
2852 /* Allocate memory for the Assoc Request frame */
2853 assoc_req = qdf_mem_malloc(sizeof(*assoc_req));
2854 if (!assoc_req)
2855 return;
2856
2857 if (!lim_alloc_assoc_req_frm_buf(assoc_req,
2858 WMA_GET_QDF_NBUF(rx_pkt_info),
2859 WMA_GET_RX_MAC_HEADER_LEN(rx_pkt_info),
2860 frame_len))
2861 goto error;
2862
2863 lim_proc_assoc_req_frm_cmn(mac_ctx, sub_type, session, hdr->sa,
2864 assoc_req, 0);
2865
2866 if (sub_type == LIM_ASSOC) {
2867 lim_cp_stats_cstats_log_assoc_req_evt
2868 (session, CSTATS_DIR_RX, hdr->bssId, hdr->sa,
2869 assoc_req->ssId.length, assoc_req->ssId.ssId,
2870 assoc_req->HTCaps.present, assoc_req->VHTCaps.present,
2871 assoc_req->he_cap.present, assoc_req->eht_cap.present,
2872 false);
2873 } else if (sub_type == LIM_REASSOC) {
2874 lim_cp_stats_cstats_log_assoc_req_evt
2875 (session, CSTATS_DIR_RX, hdr->bssId, hdr->sa,
2876 assoc_req->ssId.length, assoc_req->ssId.ssId,
2877 assoc_req->HTCaps.present, assoc_req->VHTCaps.present,
2878 assoc_req->he_cap.present, assoc_req->eht_cap.present,
2879 true);
2880 }
2881
2882 return;
2883 error:
2884 if (assoc_req) {
2885 lim_free_assoc_req_frm_buf(assoc_req);
2886 qdf_mem_free(assoc_req);
2887 }
2888 }
2889
2890 #ifdef FEATURE_WLAN_WAPI
2891 /**
2892 * lim_fill_assoc_ind_wapi_info()- Updates WAPI data in assoc indication
2893 * @mac_ctx: Global Mac context
2894 * @assoc_req: pointer to association request
2895 * @assoc_ind: Pointer to association indication
2896 * @wpsie: WPS IE
2897 *
2898 * This function updates WAPI meta data in association indication message
2899 * sent to SME.
2900 *
2901 * Return: None
2902 */
lim_fill_assoc_ind_wapi_info(struct mac_context * mac_ctx,tpSirAssocReq assoc_req,tpLimMlmAssocInd assoc_ind,const uint8_t * wpsie)2903 static void lim_fill_assoc_ind_wapi_info(struct mac_context *mac_ctx,
2904 tpSirAssocReq assoc_req, tpLimMlmAssocInd assoc_ind,
2905 const uint8_t *wpsie)
2906 {
2907 if (assoc_req->wapiPresent && (!wpsie)) {
2908 pe_debug("Received WAPI IE length in Assoc Req is %d",
2909 assoc_req->wapi.length);
2910 assoc_ind->wapiIE.wapiIEdata[0] = WLAN_ELEMID_WAPI;
2911 assoc_ind->wapiIE.wapiIEdata[1] = assoc_req->wapi.length;
2912 qdf_mem_copy(&assoc_ind->wapiIE.wapiIEdata[2],
2913 assoc_req->wapi.info, assoc_req->wapi.length);
2914 assoc_ind->wapiIE.length =
2915 2 + assoc_req->wapi.length;
2916 }
2917 return;
2918 }
2919 #else
lim_fill_assoc_ind_wapi_info(struct mac_context * mac_ctx,tpSirAssocReq assoc_req,tpLimMlmAssocInd assoc_ind,const uint8_t * wpsie)2920 static void lim_fill_assoc_ind_wapi_info(
2921 struct mac_context *mac_ctx,
2922 tpSirAssocReq assoc_req, tpLimMlmAssocInd assoc_ind,
2923 const uint8_t *wpsie)
2924 {
2925 }
2926 #endif
2927
2928 #ifdef WLAN_FEATURE_11AX
lim_fill_assoc_he_info(struct mac_context * mac_ctx,struct pe_session * session_entry,tpSirAssocReq assoc_req,tpLimMlmAssocInd assoc_ind)2929 static bool lim_fill_assoc_he_info(struct mac_context *mac_ctx,
2930 struct pe_session *session_entry,
2931 tpSirAssocReq assoc_req,
2932 tpLimMlmAssocInd assoc_ind)
2933 {
2934 if (session_entry->he_capable && assoc_req->he_cap.present) {
2935 if (session_entry->limRFBand == REG_BAND_2G) {
2936 if (session_entry->ch_width == CH_WIDTH_20MHZ)
2937 assoc_ind->chan_info.info = MODE_11AX_HE20;
2938 else if (session_entry->ch_width == CH_WIDTH_40MHZ &&
2939 assoc_req->he_cap.chan_width_0 == 1)
2940 assoc_ind->chan_info.info = MODE_11AX_HE40;
2941 else
2942 assoc_ind->chan_info.info = MODE_11AX_HE20;
2943 } else {
2944 if (session_entry->ch_width == CH_WIDTH_160MHZ &&
2945 assoc_req->he_cap.chan_width_2 == 1)
2946 assoc_ind->chan_info.info = MODE_11AX_HE160;
2947 else if (session_entry->ch_width >= CH_WIDTH_80MHZ &&
2948 assoc_req->he_cap.chan_width_1 == 1)
2949 assoc_ind->chan_info.info = MODE_11AX_HE80;
2950 else if (session_entry->ch_width >= CH_WIDTH_40MHZ &&
2951 assoc_req->he_cap.chan_width_1 == 1)
2952 assoc_ind->chan_info.info = MODE_11AX_HE40;
2953 else
2954 assoc_ind->chan_info.info = MODE_11AX_HE20;
2955 }
2956 return true;
2957 }
2958
2959 return false;
2960 }
2961 #else
lim_fill_assoc_he_info(struct mac_context * mac_ctx,struct pe_session * session_entry,tpSirAssocReq assoc_req,tpLimMlmAssocInd assoc_ind)2962 static bool lim_fill_assoc_he_info(struct mac_context *mac_ctx,
2963 struct pe_session *session_entry,
2964 tpSirAssocReq assoc_req,
2965 tpLimMlmAssocInd assoc_ind)
2966 {
2967 return false;
2968 }
2969 #endif
2970 /**
2971 * lim_fill_assoc_ind_info() - Updates HE/VHT/HT information in assoc indication
2972 * @mac_ctx: Global Mac context
2973 * @assoc_req: pointer to association request
2974 * @session_entry: PE session entry
2975 * @assoc_ind: Pointer to association indication
2976 *
2977 * This function updates VHT information in association indication message
2978 * sent to SME.
2979 *
2980 * Return: None
2981 */
lim_fill_assoc_ind_info(struct mac_context * mac_ctx,struct pe_session * session_entry,tpSirAssocReq assoc_req,tpLimMlmAssocInd assoc_ind,tpDphHashNode sta_ds)2982 static void lim_fill_assoc_ind_info(struct mac_context *mac_ctx,
2983 struct pe_session *session_entry,
2984 tpSirAssocReq assoc_req,
2985 tpLimMlmAssocInd assoc_ind,
2986 tpDphHashNode sta_ds)
2987 {
2988 uint8_t chan;
2989 uint8_t i;
2990 bool nw_type_11b = true;
2991 uint32_t cfreq = 0;
2992 enum reg_wifi_band band;
2993
2994 band = wlan_reg_freq_to_band(session_entry->curr_op_freq);
2995 cfreq = wlan_reg_chan_band_to_freq(mac_ctx->pdev,
2996 session_entry->ch_center_freq_seg0, BIT(band));
2997 assoc_ind->chan_info.band_center_freq1 = cfreq;
2998 if (session_entry->ch_center_freq_seg1) {
2999 cfreq = wlan_reg_chan_band_to_freq(mac_ctx->pdev,
3000 session_entry->ch_center_freq_seg1, BIT(band));
3001 assoc_ind->chan_info.band_center_freq2 = cfreq;
3002 }
3003 if (session_entry->ch_width == CH_WIDTH_40MHZ) {
3004 if (session_entry->htSecondaryChannelOffset ==
3005 PHY_DOUBLE_CHANNEL_LOW_PRIMARY)
3006 assoc_ind->chan_info.band_center_freq1 += 10;
3007 else
3008 assoc_ind->chan_info.band_center_freq1 -= 10;
3009 }
3010 if (lim_fill_assoc_he_info(mac_ctx, session_entry,
3011 assoc_req, assoc_ind))
3012 return;
3013
3014 if (session_entry->limRFBand == REG_BAND_2G) {
3015 if (session_entry->vhtCapability
3016 && assoc_req->VHTCaps.present) {
3017 assoc_ind->chan_info.info = MODE_11AC_VHT20_2G;
3018 } else if (session_entry->htCapability
3019 && assoc_req->HTCaps.present) {
3020 assoc_ind->chan_info.info = MODE_11NG_HT20;
3021 } else {
3022 for (i = 0; i < SIR_NUM_11A_RATES; i++) {
3023 if (sirIsArate(sta_ds->
3024 supportedRates.llaRates[i]
3025 & 0x7F)) {
3026 assoc_ind->chan_info.info = MODE_11G;
3027 nw_type_11b = false;
3028 break;
3029 }
3030 }
3031 if (nw_type_11b)
3032 assoc_ind->chan_info.info = MODE_11B;
3033 }
3034 return;
3035 }
3036
3037 if (session_entry->vhtCapability && assoc_req->VHTCaps.present) {
3038 if ((session_entry->ch_width > CH_WIDTH_40MHZ)
3039 && assoc_req->HTCaps.supportedChannelWidthSet) {
3040 chan = session_entry->ch_center_freq_seg0;
3041 assoc_ind->chan_info.band_center_freq1 =
3042 cds_chan_to_freq(chan);
3043 assoc_ind->chan_info.info = MODE_11AC_VHT80;
3044 return;
3045 }
3046
3047 if ((session_entry->ch_width == CH_WIDTH_40MHZ)
3048 && assoc_req->HTCaps.supportedChannelWidthSet) {
3049 assoc_ind->chan_info.info = MODE_11AC_VHT40;
3050 return;
3051 }
3052
3053 assoc_ind->chan_info.info = MODE_11AC_VHT20;
3054 return;
3055 }
3056
3057 if (session_entry->htCapability && assoc_req->HTCaps.present) {
3058 if ((session_entry->ch_width == CH_WIDTH_40MHZ)
3059 && assoc_req->HTCaps.supportedChannelWidthSet) {
3060 assoc_ind->chan_info.info = MODE_11NA_HT40;
3061 return;
3062 }
3063
3064 assoc_ind->chan_info.info = MODE_11NA_HT20;
3065 return;
3066 }
3067
3068 assoc_ind->chan_info.info = MODE_11A;
3069 return;
3070 }
3071
fill_mlm_assoc_ind_vht(tpSirAssocReq assocreq,tpDphHashNode stads,tpLimMlmAssocInd assocind)3072 static void fill_mlm_assoc_ind_vht(tpSirAssocReq assocreq,
3073 tpDphHashNode stads,
3074 tpLimMlmAssocInd assocind)
3075 {
3076 if (stads->mlmStaContext.vhtCapability) {
3077 /* ampdu */
3078 assocind->ampdu = true;
3079
3080 /* sgi */
3081 if (assocreq->VHTCaps.shortGI80MHz ||
3082 assocreq->VHTCaps.shortGI160and80plus80MHz)
3083 assocind->sgi_enable = true;
3084
3085 /* stbc */
3086 assocind->tx_stbc = assocreq->VHTCaps.txSTBC;
3087 assocind->rx_stbc = assocreq->VHTCaps.rxSTBC;
3088
3089 /* ch width */
3090 assocind->ch_width = stads->vhtSupportedChannelWidthSet ?
3091 eHT_CHANNEL_WIDTH_80MHZ :
3092 stads->htSupportedChannelWidthSet ?
3093 eHT_CHANNEL_WIDTH_40MHZ : eHT_CHANNEL_WIDTH_20MHZ;
3094
3095 /* mode */
3096 assocind->mode = SIR_SME_PHY_MODE_VHT;
3097 assocind->rx_mcs_map = assocreq->VHTCaps.rxMCSMap & 0xff;
3098 assocind->tx_mcs_map = assocreq->VHTCaps.txMCSMap & 0xff;
3099 }
3100 }
3101
3102 /**
3103 *lim_convert_channel_width_enum() - map between two channel width enums
3104 *@ch_width: channel width of enum type phy_ch_width
3105 *
3106 *Return: channel width of enum type tSirMacHTChannelWidth
3107 */
3108 static tSirMacHTChannelWidth
lim_convert_channel_width_enum(enum phy_ch_width ch_width)3109 lim_convert_channel_width_enum(enum phy_ch_width ch_width)
3110 {
3111 switch (ch_width) {
3112 case CH_WIDTH_20MHZ:
3113 return eHT_CHANNEL_WIDTH_20MHZ;
3114 case CH_WIDTH_40MHZ:
3115 return eHT_CHANNEL_WIDTH_40MHZ;
3116 case CH_WIDTH_80MHZ:
3117 return eHT_CHANNEL_WIDTH_80MHZ;
3118 case CH_WIDTH_160MHZ:
3119 return eHT_CHANNEL_WIDTH_160MHZ;
3120 case CH_WIDTH_80P80MHZ:
3121 return eHT_CHANNEL_WIDTH_80P80MHZ;
3122 case CH_WIDTH_320MHZ:
3123 return eHT_CHANNEL_WIDTH_320MHZ;
3124 case CH_WIDTH_MAX:
3125 return eHT_MAX_CHANNEL_WIDTH;
3126 case CH_WIDTH_5MHZ:
3127 break;
3128 case CH_WIDTH_10MHZ:
3129 break;
3130 case CH_WIDTH_INVALID:
3131 break;
3132 }
3133 pe_debug("invalid enum: %d", ch_width);
3134 return eHT_CHANNEL_WIDTH_20MHZ;
3135 }
3136
3137 /**
3138 * lim_convert_rate_flags_enum() - map between channel width and rate flag enums
3139 * @rate_flags: the current rate flags
3140 * @ch_width: channel width of enum type phy_ch_width
3141 *
3142 * Return: updated rate flags per ch width
3143 */
lim_convert_rate_flags_enum(uint32_t rate_flags,enum phy_ch_width ch_width)3144 static uint32_t lim_convert_rate_flags_enum(uint32_t rate_flags,
3145 enum phy_ch_width ch_width)
3146 {
3147 if (rate_flags & (TX_RATE_HE160 |
3148 TX_RATE_HE80 |
3149 TX_RATE_HE40 |
3150 TX_RATE_HE20)) {
3151 switch (ch_width) {
3152 case CH_WIDTH_20MHZ:
3153 rate_flags |= TX_RATE_HE20;
3154 break;
3155 case CH_WIDTH_40MHZ:
3156 rate_flags |= TX_RATE_HE40;
3157 break;
3158 case CH_WIDTH_80MHZ:
3159 rate_flags |= TX_RATE_HE80;
3160 break;
3161 case CH_WIDTH_160MHZ:
3162 case CH_WIDTH_80P80MHZ:
3163 rate_flags |= TX_RATE_HE160;
3164 break;
3165 default:
3166 break;
3167 }
3168 } else if (rate_flags & (TX_RATE_VHT160 |
3169 TX_RATE_VHT80 |
3170 TX_RATE_VHT40 |
3171 TX_RATE_VHT20)) {
3172 switch (ch_width) {
3173 case CH_WIDTH_20MHZ:
3174 rate_flags |= TX_RATE_VHT20;
3175 break;
3176 case CH_WIDTH_40MHZ:
3177 rate_flags |= TX_RATE_VHT40;
3178 break;
3179 case CH_WIDTH_80MHZ:
3180 rate_flags |= TX_RATE_VHT80;
3181 break;
3182 case CH_WIDTH_160MHZ:
3183 case CH_WIDTH_80P80MHZ:
3184 rate_flags |= TX_RATE_VHT160;
3185 break;
3186 default:
3187 break;
3188 }
3189 } else {
3190 switch (ch_width) {
3191 case CH_WIDTH_20MHZ:
3192 rate_flags |= TX_RATE_HT20;
3193 break;
3194 case CH_WIDTH_40MHZ:
3195 rate_flags |= TX_RATE_HT40;
3196 break;
3197 default:
3198 break;
3199 }
3200 }
3201 return rate_flags;
3202 }
3203
lim_fill_assoc_ind_he_bw_info(tpLimMlmAssocInd assoc_ind,tpDphHashNode sta_ds,struct pe_session * session_entry)3204 static void lim_fill_assoc_ind_he_bw_info(tpLimMlmAssocInd assoc_ind,
3205 tpDphHashNode sta_ds,
3206 struct pe_session *session_entry)
3207 {
3208 if (lim_is_sta_he_capable(sta_ds) &&
3209 lim_is_session_he_capable(session_entry)) {
3210 assoc_ind->ch_width =
3211 lim_convert_channel_width_enum(sta_ds->ch_width);
3212 assoc_ind->chan_info.rate_flags =
3213 lim_convert_rate_flags_enum(assoc_ind->chan_info.rate_flags,
3214 sta_ds->ch_width);
3215 }
3216 }
3217
3218 /**
3219 * lim_fill_assoc_ind_real_max_mcs_idx() - fill max real mcs index to assoc ind
3220 * @assoc_ind: assoc_ind to fill
3221 * @assoc_req: pointer to tpSirAssocReq
3222 * @sta_ds: pointer to tpDphHashNode
3223 * @session: pointer to session
3224 *
3225 * Return: void
3226 */
lim_fill_assoc_ind_real_max_mcs_idx(tpLimMlmAssocInd assoc_ind,tpSirAssocReq assoc_req,tpDphHashNode sta_ds,struct pe_session * session)3227 static void lim_fill_assoc_ind_real_max_mcs_idx(tpLimMlmAssocInd assoc_ind,
3228 tpSirAssocReq assoc_req,
3229 tpDphHashNode sta_ds,
3230 struct pe_session *session)
3231 {
3232 assoc_ind->max_real_mcs_idx = INVALID_MCS_NSS_INDEX;
3233
3234 if (lim_is_sta_he_capable(sta_ds) &&
3235 lim_is_session_he_capable(session))
3236 assoc_ind->max_real_mcs_idx = lim_get_he_max_mcs_idx(
3237 sta_ds->ch_width, &assoc_req->he_cap);
3238
3239 if (assoc_ind->max_real_mcs_idx == INVALID_MCS_NSS_INDEX &&
3240 sta_ds->mlmStaContext.vhtCapability)
3241 assoc_ind->max_real_mcs_idx =
3242 lim_get_vht_max_mcs_idx(&assoc_req->VHTCaps);
3243
3244 if (assoc_ind->max_real_mcs_idx == INVALID_MCS_NSS_INDEX)
3245 assoc_ind->max_real_mcs_idx = assoc_ind->max_mcs_idx;
3246
3247 if (assoc_ind->max_real_mcs_idx == INVALID_MCS_NSS_INDEX)
3248 assoc_ind->max_real_mcs_idx = assoc_ind->max_ext_idx;
3249
3250 if (assoc_ind->max_real_mcs_idx == INVALID_MCS_NSS_INDEX)
3251 assoc_ind->max_real_mcs_idx = assoc_ind->max_supp_idx;
3252 }
3253
3254 #ifdef WLAN_FEATURE_11BE_MLO
3255 static void
lim_fill_lim_assoc_ind_mac_addr_copy(tpLimMlmAssocInd assoc_ind,tpDphHashNode sta_ds,uint32_t num_bytes)3256 lim_fill_lim_assoc_ind_mac_addr_copy(tpLimMlmAssocInd assoc_ind,
3257 tpDphHashNode sta_ds,
3258 uint32_t num_bytes)
3259 {
3260 qdf_mem_copy((uint8_t *)assoc_ind->peer_mld_addr,
3261 (uint8_t *)sta_ds->mld_addr,
3262 num_bytes);
3263 }
3264 #else /* WLAN_FEATURE_11BE_MLO */
3265 static inline void
lim_fill_lim_assoc_ind_mac_addr_copy(tpLimMlmAssocInd assoc_ind,tpDphHashNode sta_ds,uint32_t num_bytes)3266 lim_fill_lim_assoc_ind_mac_addr_copy(tpLimMlmAssocInd assoc_ind,
3267 tpDphHashNode sta_ds,
3268 uint32_t num_bytes)
3269 {
3270 }
3271 #endif /* WLAN_FEATURE_11BE_MLO */
3272
lim_fill_lim_assoc_ind_params(tpLimMlmAssocInd assoc_ind,struct mac_context * mac_ctx,tpDphHashNode sta_ds,struct pe_session * session_entry)3273 bool lim_fill_lim_assoc_ind_params(
3274 tpLimMlmAssocInd assoc_ind,
3275 struct mac_context *mac_ctx,
3276 tpDphHashNode sta_ds,
3277 struct pe_session *session_entry)
3278 {
3279 tpSirAssocReq assoc_req;
3280 uint16_t rsn_len;
3281 uint32_t phy_mode;
3282 const uint8_t *wpsie = NULL;
3283 bool wme_enable;
3284 struct wlan_objmgr_vdev *vdev;
3285 struct vdev_mlme_obj *mlme_obj;
3286 uint8_t country_iso[REG_ALPHA2_LEN + 1];
3287 tDot11fIESuppOperatingClasses *oper_class;
3288
3289 if (!session_entry->parsedAssocReq) {
3290 pe_err(" Parsed Assoc req is NULL");
3291 return false;
3292 }
3293
3294 /* Get a copy of the already parsed Assoc Request */
3295 assoc_req =
3296 (tpSirAssocReq)session_entry->parsedAssocReq[sta_ds->assocId];
3297
3298 if (!assoc_req) {
3299 pe_err("assoc req for assoc_id:%d is NULL", sta_ds->assocId);
3300 return false;
3301 }
3302
3303 /* Get the phy_mode */
3304 lim_get_phy_mode(mac_ctx, &phy_mode, session_entry);
3305
3306 qdf_mem_copy((uint8_t *)assoc_ind->peerMacAddr,
3307 (uint8_t *)sta_ds->staAddr, sizeof(tSirMacAddr));
3308 lim_fill_lim_assoc_ind_mac_addr_copy(assoc_ind, sta_ds,
3309 sizeof(tSirMacAddr));
3310 assoc_ind->aid = sta_ds->assocId;
3311 qdf_mem_copy((uint8_t *)&assoc_ind->ssId,
3312 (uint8_t *)&assoc_req->ssId,
3313 assoc_req->ssId.length + 1);
3314 assoc_ind->sessionId = session_entry->peSessionId;
3315 assoc_ind->authType = sta_ds->mlmStaContext.authType;
3316 assoc_ind->akm_type = sta_ds->mlmStaContext.akm_type;
3317 assoc_ind->capabilityInfo = assoc_req->capabilityInfo;
3318
3319 /* Fill in RSN IE information */
3320 assoc_ind->rsnIE.length = 0;
3321 /* if WPS IE is present, ignore RSN IE */
3322 if (assoc_req->addIEPresent && assoc_req->addIE.length) {
3323 wpsie = limGetWscIEPtr(
3324 mac_ctx,
3325 assoc_req->addIE.addIEdata,
3326 assoc_req->addIE.length);
3327 }
3328 if (assoc_req->rsnPresent && !wpsie) {
3329 pe_debug("Assoc Req RSN IE len: %d",
3330 assoc_req->rsn.length);
3331 assoc_ind->rsnIE.length = 2 + assoc_req->rsn.length;
3332 assoc_ind->rsnIE.rsnIEdata[0] = WLAN_ELEMID_RSN;
3333 assoc_ind->rsnIE.rsnIEdata[1] =
3334 assoc_req->rsn.length;
3335 qdf_mem_copy(
3336 &assoc_ind->rsnIE.rsnIEdata[2],
3337 assoc_req->rsn.info,
3338 assoc_req->rsn.length);
3339 }
3340 /* Fill in 802.11h related info */
3341 if (assoc_req->powerCapabilityPresent &&
3342 assoc_req->supportedChannelsPresent) {
3343 assoc_ind->spectrumMgtIndicator = true;
3344 assoc_ind->powerCap.minTxPower =
3345 assoc_req->powerCapability.minTxPower;
3346 assoc_ind->powerCap.maxTxPower =
3347 assoc_req->powerCapability.maxTxPower;
3348 lim_convert_supported_channels(
3349 mac_ctx, assoc_ind,
3350 assoc_req);
3351 } else {
3352 assoc_ind->spectrumMgtIndicator = false;
3353 }
3354
3355 /* This check is to avoid extra Sec IEs present incase of WPS */
3356 if (assoc_req->wpaPresent && !wpsie) {
3357 rsn_len = assoc_ind->rsnIE.length;
3358 if ((rsn_len + assoc_req->wpa.length)
3359 >= WLAN_MAX_IE_LEN) {
3360 pe_err("rsnIEdata index out of bounds: %d",
3361 rsn_len);
3362 return false;
3363 }
3364 assoc_ind->rsnIE.rsnIEdata[rsn_len] =
3365 SIR_MAC_WPA_EID;
3366 assoc_ind->rsnIE.rsnIEdata[rsn_len + 1]
3367 = assoc_req->wpa.length;
3368 qdf_mem_copy(
3369 &assoc_ind->rsnIE.rsnIEdata[rsn_len + 2],
3370 assoc_req->wpa.info, assoc_req->wpa.length);
3371 assoc_ind->rsnIE.length += 2 + assoc_req->wpa.length;
3372 }
3373 lim_fill_assoc_ind_wapi_info(mac_ctx, assoc_req, assoc_ind, wpsie);
3374
3375 assoc_ind->addIE.length = 0;
3376 if (assoc_req->addIEPresent) {
3377 qdf_mem_copy(
3378 &assoc_ind->addIE.addIEdata,
3379 assoc_req->addIE.addIEdata,
3380 assoc_req->addIE.length);
3381 assoc_ind->addIE.length = assoc_req->addIE.length;
3382 }
3383 /*
3384 * Add HT Capabilities into addIE for OBSS
3385 * processing in hostapd
3386 */
3387 if (assoc_req->HTCaps.present) {
3388 qdf_mem_copy(&assoc_ind->ht_caps, &assoc_req->HTCaps,
3389 sizeof(tDot11fIEHTCaps));
3390 rsn_len = assoc_ind->addIE.length;
3391 if (assoc_ind->addIE.length + DOT11F_IE_HTCAPS_MIN_LEN
3392 + 2 < WLAN_MAX_IE_LEN) {
3393 assoc_ind->addIE.addIEdata[rsn_len] =
3394 WLAN_ELEMID_HTCAP_ANA;
3395 assoc_ind->addIE.addIEdata[rsn_len + 1] =
3396 DOT11F_IE_HTCAPS_MIN_LEN;
3397 qdf_mem_copy(
3398 &assoc_ind->addIE.addIEdata[rsn_len + 2],
3399 ((uint8_t *)&assoc_req->HTCaps) + 1,
3400 DOT11F_IE_HTCAPS_MIN_LEN);
3401 assoc_ind->addIE.length +=
3402 2 + DOT11F_IE_HTCAPS_MIN_LEN;
3403 } else {
3404 pe_err("Fail:HT capabilities IE to addIE");
3405 }
3406 }
3407
3408 if (assoc_req->wmeInfoPresent) {
3409 /* Set whether AP is enabled with WMM or not */
3410 wme_enable = mac_ctx->mlme_cfg->wmm_params.wme_enabled;
3411 assoc_ind->WmmStaInfoPresent = wme_enable;
3412 /*
3413 * Note: we are not rejecting association here
3414 * because IOT will fail
3415 */
3416 }
3417 /* Required for indicating the frames to upper layer */
3418 assoc_ind->assocReqLength = assoc_req->assocReqFrameLength;
3419 assoc_ind->assocReqPtr = assoc_req->assocReqFrame;
3420
3421 assoc_ind->chan_info.mhz = session_entry->curr_op_freq;
3422 assoc_ind->chan_info.band_center_freq1 =
3423 session_entry->curr_op_freq;
3424 assoc_ind->chan_info.band_center_freq2 = 0;
3425 assoc_ind->chan_info.reg_info_1 =
3426 (session_entry->maxTxPower << 16);
3427 assoc_ind->chan_info.reg_info_2 =
3428 (session_entry->maxTxPower << 8);
3429 assoc_ind->chan_info.nss = sta_ds->nss;
3430 assoc_ind->chan_info.rate_flags =
3431 lim_get_max_rate_flags(mac_ctx, sta_ds);
3432 assoc_ind->ampdu = false;
3433 assoc_ind->sgi_enable = false;
3434 assoc_ind->tx_stbc = false;
3435 assoc_ind->rx_stbc = false;
3436 assoc_ind->ch_width = eHT_CHANNEL_WIDTH_20MHZ;
3437 assoc_ind->mode = SIR_SME_PHY_MODE_LEGACY;
3438 assoc_ind->max_supp_idx = INVALID_MCS_NSS_INDEX;
3439 assoc_ind->max_ext_idx = INVALID_MCS_NSS_INDEX;
3440 assoc_ind->max_mcs_idx = INVALID_MCS_NSS_INDEX;
3441 assoc_ind->rx_mcs_map = 0xff;
3442 assoc_ind->tx_mcs_map = 0xff;
3443
3444 if (assoc_req->supportedRates.numRates)
3445 assoc_ind->max_supp_idx =
3446 lim_get_max_rate_idx(&assoc_req->supportedRates);
3447 if (assoc_req->extendedRates.numRates)
3448 assoc_ind->max_ext_idx =
3449 lim_get_max_rate_idx(&assoc_req->extendedRates);
3450
3451 if (sta_ds->mlmStaContext.htCapability) {
3452 /* ampdu */
3453 assoc_ind->ampdu = true;
3454
3455 /* sgi */
3456 if (sta_ds->htShortGI20Mhz || sta_ds->htShortGI40Mhz)
3457 assoc_ind->sgi_enable = true;
3458
3459 /* stbc */
3460 assoc_ind->tx_stbc = assoc_req->HTCaps.txSTBC;
3461 assoc_ind->rx_stbc = assoc_req->HTCaps.rxSTBC;
3462
3463 /* ch width */
3464 assoc_ind->ch_width =
3465 sta_ds->htSupportedChannelWidthSet ?
3466 eHT_CHANNEL_WIDTH_40MHZ :
3467 eHT_CHANNEL_WIDTH_20MHZ;
3468 /* mode */
3469 assoc_ind->mode = SIR_SME_PHY_MODE_HT;
3470 assoc_ind->max_mcs_idx = lim_get_ht_max_mcs_idx(
3471 &assoc_req->HTCaps);
3472 }
3473 fill_mlm_assoc_ind_vht(assoc_req, sta_ds, assoc_ind);
3474 if (assoc_req->ExtCap.present) {
3475 assoc_ind->ecsa_capable =
3476 ((struct s_ext_cap *)assoc_req->ExtCap.bytes)->ext_chan_switch;
3477 if (assoc_req->ExtCap.num_bytes >= sizeof(assoc_ind->ext_cap))
3478 qdf_mem_copy(&assoc_ind->ext_cap,
3479 assoc_req->ExtCap.bytes,
3480 sizeof(assoc_ind->ext_cap));
3481 else
3482 qdf_mem_copy(&assoc_ind->ext_cap,
3483 assoc_req->ExtCap.bytes,
3484 assoc_req->ExtCap.num_bytes);
3485 }
3486
3487 if (assoc_req->supp_operating_classes.present) {
3488 oper_class = &assoc_req->supp_operating_classes;
3489 qdf_mem_zero(country_iso, sizeof(country_iso));
3490 country_iso[2] = OP_CLASS_GLOBAL;
3491 assoc_ind->supported_band =
3492 wlan_reg_get_band_cap_from_op_class(
3493 country_iso,
3494 oper_class->num_classes,
3495 oper_class->classes);
3496 }
3497
3498 /* updates VHT information in assoc indication */
3499 if (assoc_req->VHTCaps.present)
3500 qdf_mem_copy(&assoc_ind->vht_caps, &assoc_req->VHTCaps,
3501 sizeof(tDot11fIEVHTCaps));
3502 else if (assoc_req->vendor_vht_ie.VHTCaps.present)
3503 qdf_mem_copy(&assoc_ind->vht_caps,
3504 &assoc_req->vendor_vht_ie.VHTCaps,
3505 sizeof(tDot11fIEVHTCaps));
3506
3507 lim_fill_assoc_ind_info(mac_ctx, session_entry, assoc_req,
3508 assoc_ind, sta_ds);
3509 pe_debug("ch_width: %d vht_cap %d ht_cap %d chan_info %d center_freq1 %d",
3510 session_entry->ch_width,
3511 session_entry->vhtCapability, session_entry->htCapability,
3512 assoc_ind->chan_info.info,
3513 assoc_ind->chan_info.band_center_freq1);
3514 assoc_ind->he_caps_present = assoc_req->he_cap.present;
3515 assoc_ind->eht_caps_present = assoc_req->eht_cap.present;
3516 assoc_ind->is_sae_authenticated =
3517 assoc_req->is_sae_authenticated;
3518 /* updates HE bandwidth in assoc indication */
3519 lim_fill_assoc_ind_he_bw_info(assoc_ind, sta_ds, session_entry);
3520 lim_fill_assoc_ind_real_max_mcs_idx(assoc_ind, assoc_req,
3521 sta_ds, session_entry);
3522
3523 vdev = session_entry->vdev;
3524 if (!vdev)
3525 return true;
3526
3527 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev);
3528 if (!mlme_obj)
3529 pe_err("vdev component object is NULL");
3530 else
3531 qdf_mem_copy(
3532 &mlme_obj->ext_vdev_ptr->connect_info.chan_info,
3533 &assoc_ind->chan_info,
3534 sizeof(mlme_obj->ext_vdev_ptr->connect_info.chan_info));
3535
3536 return true;
3537 }
3538
lim_send_mlm_assoc_ind(struct mac_context * mac_ctx,tpDphHashNode sta_ds,struct pe_session * session_entry)3539 QDF_STATUS lim_send_mlm_assoc_ind(struct mac_context *mac_ctx,
3540 tpDphHashNode sta_ds,
3541 struct pe_session *session_entry)
3542 {
3543 tpLimMlmAssocInd assoc_ind;
3544 tpSirAssocReq assoc_req;
3545 uint16_t temp;
3546 uint32_t phy_mode;
3547 uint8_t sub_type;
3548
3549 if (!session_entry->parsedAssocReq) {
3550 pe_err(" Parsed Assoc req is NULL");
3551 return QDF_STATUS_E_INVAL;
3552 }
3553
3554 /* Get a copy of the already parsed Assoc Request */
3555 assoc_req =
3556 (tpSirAssocReq) session_entry->parsedAssocReq[sta_ds->assocId];
3557
3558 if (!assoc_req) {
3559 pe_err("assoc req for assoc_id:%d is NULL", sta_ds->assocId);
3560 return QDF_STATUS_E_INVAL;
3561 }
3562
3563 /* Get the phy_mode */
3564 lim_get_phy_mode(mac_ctx, &phy_mode, session_entry);
3565
3566 /* Determine if its Assoc or ReAssoc Request */
3567 if (assoc_req->reassocRequest == 1)
3568 sub_type = LIM_REASSOC;
3569 else
3570 sub_type = LIM_ASSOC;
3571
3572 pe_debug("Sessionid: %d ssid: " QDF_SSID_FMT " sub_type: %d Associd: %d staAddr: "
3573 QDF_MAC_ADDR_FMT, session_entry->peSessionId,
3574 QDF_SSID_REF(assoc_req->ssId.length, assoc_req->ssId.ssId),
3575 sub_type, sta_ds->assocId,
3576 QDF_MAC_ADDR_REF(sta_ds->staAddr));
3577
3578 wlan_son_ind_assoc_req_frm(session_entry->vdev, sta_ds->staAddr,
3579 assoc_req->reassocRequest,
3580 qdf_nbuf_data(assoc_req->assoc_req_buf),
3581 qdf_nbuf_len(assoc_req->assoc_req_buf),
3582 QDF_STATUS_SUCCESS);
3583
3584 if (sub_type == LIM_ASSOC || sub_type == LIM_REASSOC) {
3585 temp = sizeof(tLimMlmAssocInd);
3586
3587 assoc_ind = qdf_mem_malloc(temp);
3588 if (!assoc_ind) {
3589 if (lim_is_mlo_conn(session_entry, sta_ds))
3590 lim_release_mlo_conn_idx(mac_ctx,
3591 sta_ds->assocId,
3592 session_entry, false);
3593 else
3594 lim_release_peer_idx(mac_ctx, sta_ds->assocId,
3595 session_entry);
3596 return QDF_STATUS_E_INVAL;
3597 }
3598 if (!lim_fill_lim_assoc_ind_params(assoc_ind, mac_ctx,
3599 sta_ds, session_entry)) {
3600 qdf_mem_free(assoc_ind);
3601 return QDF_STATUS_E_INVAL;
3602 }
3603
3604 pe_debug("assoc_ind->akm_type:%d ", assoc_ind->akm_type);
3605 if (assoc_ind->akm_type == ANI_AKM_TYPE_FT_RSN_PSK) {
3606 lim_send_sme_mgmt_frame_ind(mac_ctx, sub_type,
3607 qdf_nbuf_data(assoc_req->assoc_req_buf),
3608 qdf_nbuf_len(assoc_req->assoc_req_buf),
3609 session_entry->smeSessionId,
3610 0, 0, RXMGMT_FLAG_NONE);
3611 }
3612 lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_IND,
3613 (uint32_t *)assoc_ind);
3614 qdf_mem_free(assoc_ind);
3615 }
3616
3617 return QDF_STATUS_SUCCESS;
3618 }
3619