1 /** @file mlan_join.c
2 *
3 * @brief This file provides Functions implementing wlan infrastructure
4 * and adhoc join routines IOCTL handlers as well as command preparation
5 * and response routines for sending adhoc start, adhoc join, and
6 * association commands to the firmware.
7 *
8 * Copyright 2008-2024 NXP
9 *
10 * SPDX-License-Identifier: BSD-3-Clause
11 *
12 */
13
14 /******************************************************
15 Change log:
16 10/30/2008: initial version
17 ******************************************************/
18 #include <mlan_api.h>
19
20 /* Additional WMSDK header files */
21 #include <wmerrno.h>
22 #include <osa.h>
23
24 /* Always keep this include at the end of all include files */
25 #include <mlan_remap_mem_operations.h>
26 #if CONFIG_WPS2
27 #include "wifi_nxp_wps.h"
28 #endif
29 /********************************************************
30 Local Constants
31 ********************************************************/
32
33 /********************************************************
34 Local Variables
35 ********************************************************/
36
37 /********************************************************
38 Global Variables
39 ********************************************************/
40
41 /********************************************************
42 Local Functions
43 ********************************************************/
44 /**
45 * @brief Append a generic IE as a pass through TLV to a TLV buffer.
46 *
47 * This function is called from the network join command prep. routine.
48 * If the IE buffer has been setup by the application, this routine appends
49 * the buffer as a pass through TLV type to the request.
50 *
51 * @param priv A pointer to mlan_private structure
52 * @param ppbuffer pointer to command buffer pointer
53 *
54 * @return bytes added to the buffer
55 */
wlan_cmd_append_generic_ie(mlan_private * priv,t_u8 ** ppbuffer)56 static int wlan_cmd_append_generic_ie(mlan_private *priv, t_u8 **ppbuffer)
57 {
58 int ret_len = 0;
59 MrvlIEtypesHeader_t ie_header;
60
61 ENTER();
62
63 /* Null Checks */
64 if (ppbuffer == MNULL)
65 {
66 LEAVE();
67 return 0;
68 }
69 if (*ppbuffer == MNULL)
70 {
71 LEAVE();
72 return 0;
73 }
74
75 /*
76 * If there is a generic ie buffer setup, append it to the return
77 * parameter buffer pointer.
78 */
79 if (priv->gen_ie_buf_len)
80 {
81 PRINTM(MINFO, "append generic IE %d to %p\n", priv->gen_ie_buf_len, *ppbuffer);
82
83 /* Wrap the generic IE buffer with a pass through TLV type */
84 ie_header.type = wlan_cpu_to_le16(TLV_TYPE_PASSTHROUGH);
85 ie_header.len = wlan_cpu_to_le16(priv->gen_ie_buf_len);
86 (void)__memcpy(priv->adapter, *ppbuffer, &ie_header, sizeof(ie_header));
87
88 /* Increment the return size and the return buffer pointer param */
89 *ppbuffer += sizeof(ie_header);
90 ret_len += sizeof(ie_header);
91
92 /* Copy the generic IE buffer to the output buffer, advance pointer */
93 (void)__memcpy(priv->adapter, *ppbuffer, priv->gen_ie_buf, priv->gen_ie_buf_len);
94
95 /* Increment the return size and the return buffer pointer param */
96 *ppbuffer += priv->gen_ie_buf_len;
97 ret_len += priv->gen_ie_buf_len;
98
99 /* Reset the generic IE buffer */
100 priv->gen_ie_buf_len = 0;
101 }
102
103 /* return the length appended to the buffer */
104 LEAVE();
105 return ret_len;
106 }
107
108 /**
109 * @brief This function finds out the common rates between rate1 and rate2.
110 *
111 * It will fill common rates in rate1 as output if found.
112 *
113 * NOTE: Setting the MSB of the basic rates needs to be taken
114 * care of, either before or after calling this function
115 *
116 * @param pmpriv A pointer to mlan_private structure
117 * @param rate1 the buffer which keeps input and output
118 * @param rate1_size the size of rate1 buffer
119 * @param rate2 the buffer which keeps rate2
120 * @param rate2_size the size of rate2 buffer.
121 *
122 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
123 */
wlan_get_common_rates(IN mlan_private * pmpriv,IN t_u8 * rate1,IN t_u32 rate1_size,IN t_u8 * rate2,IN t_u32 rate2_size)124 static mlan_status wlan_get_common_rates(
125 IN mlan_private *pmpriv, IN t_u8 *rate1, IN t_u32 rate1_size, IN t_u8 *rate2, IN t_u32 rate2_size)
126 {
127 mlan_status ret = MLAN_STATUS_SUCCESS;
128 #if !CONFIG_MEM_POOLS
129 mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
130 #endif
131 t_u8 *ptr = rate1;
132 t_u8 *tmp = MNULL;
133 t_u32 i, j;
134
135 ENTER();
136
137 #if !CONFIG_MEM_POOLS
138 ret = pcb->moal_malloc(pmpriv->adapter->pmoal_handle, rate1_size, MLAN_MEM_DEF, &tmp);
139 if (ret != MLAN_STATUS_SUCCESS || (tmp == MNULL))
140 #else
141 tmp = OSA_MemoryPoolAllocate(buf_128_MemoryPool);
142 if (tmp == MNULL)
143 #endif
144 {
145 PRINTM(MERROR, "Failed to allocate buffer\n");
146 ret = MLAN_STATUS_FAILURE;
147 goto done;
148 }
149
150 (void)__memcpy(pmpriv->adapter, tmp, rate1, rate1_size);
151 (void)__memset(pmpriv->adapter, rate1, 0, rate1_size);
152
153 for (i = 0; rate2[i] && i < rate2_size; i++)
154 {
155 for (j = 0; tmp[j] && j < rate1_size; j++)
156 {
157 /* Check common rate, excluding the bit for basic rate */
158 if ((rate2[i] & 0x7FU) == (tmp[j] & 0x7FU))
159 {
160 *rate1++ = tmp[j];
161 break;
162 }
163 }
164 }
165
166 HEXDUMP("rate1 (AP) Rates", tmp, rate1_size);
167 HEXDUMP("rate2 (Card) Rates", rate2, rate2_size);
168 HEXDUMP("Common Rates", ptr, rate1 - ptr);
169 PRINTM(MINFO, "Tx DataRate is set to 0x%X\n", pmpriv->data_rate);
170
171 if (!pmpriv->is_data_rate_auto)
172 {
173 while (*ptr != 0U)
174 {
175 if ((*ptr & 0x7fU) == pmpriv->data_rate)
176 {
177 ret = MLAN_STATUS_SUCCESS;
178 goto done;
179 }
180 ptr++;
181 }
182 PRINTM(MMSG,
183 "Previously set fixed data rate %#x is not "
184 "compatible with the network\n",
185 pmpriv->data_rate);
186
187 ret = MLAN_STATUS_FAILURE;
188 goto done;
189 }
190
191 ret = MLAN_STATUS_SUCCESS;
192 done:
193 if (tmp != MNULL)
194 {
195 #if !CONFIG_MEM_POOLS
196 (void)pcb->moal_mfree(pmpriv->adapter->pmoal_handle, tmp);
197 #else
198 OSA_MemoryPoolFree(buf_128_MemoryPool, tmp);
199 #endif
200 }
201
202 LEAVE();
203 return ret;
204 }
205
206 #if 0
207 /**
208 * @brief Create the intersection of the rates supported by a target BSS and
209 * our pmadapter settings for use in an assoc/join command.
210 *
211 * @param pmpriv A pointer to mlan_private structure
212 * @param pbss_desc BSS Descriptor whose rates are used in the setup
213 * @param pout_rates Output: Octet array of rates common between the BSS
214 * and the pmadapter supported rates settings
215 * @param pout_rates_size Output: Number of rates/octets set in pout_rates
216 *
217 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
218 */
219 static mlan_status wlan_setup_rates_from_bssdesc(IN mlan_private *pmpriv,
220 IN BSSDescriptor_t *pbss_desc,
221 OUT t_u8 *pout_rates,
222 OUT t_u32 *pout_rates_size)
223 {
224 t_u8 card_rates[WLAN_SUPPORTED_RATES] = {0x0};
225 t_u32 card_rates_size = 0;
226 ENTER();
227
228 (void)__memset(pmadapter, card_rates, 0x00, WLAN_SUPPORTED_RATES);
229 /* Copy AP supported rates */
230 (void)__memcpy(pmpriv->adapter, pout_rates, pbss_desc->supported_rates, WLAN_SUPPORTED_RATES);
231 /* Get the STA supported rates */
232 card_rates_size = wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode, pmpriv->config_bands, card_rates);
233 /* Get the common rates between AP and STA supported rates */
234 if (wlan_get_common_rates(pmpriv, pout_rates, WLAN_SUPPORTED_RATES, card_rates, card_rates_size) !=
235 MLAN_STATUS_SUCCESS)
236 {
237 *pout_rates_size = 0;
238 PRINTM(MERROR, "wlan_get_common_rates failed\n");
239 LEAVE();
240 return MLAN_STATUS_FAILURE;
241 }
242
243 *pout_rates_size = MIN(wlan_strlen((char *)pout_rates), WLAN_SUPPORTED_RATES);
244
245 LEAVE();
246 return MLAN_STATUS_SUCCESS;
247 }
248 #endif
249
250 /**
251 * @brief Create the intersection of the rates supported by a target BSS and
252 * our pmadapter settings for use in an assoc/join command.
253 *
254 * @param pmpriv A pointer to mlan_private structure
255 * @param pbss_desc BSS Descriptor whose rates are used in the setup
256 * @param pout_rates Output: Octet array of rates common between the BSS
257 * and the pmadapter supported rates settings
258 * @param pout_rates_size Output: Number of rates/octets set in pout_rates
259 *
260 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
261 */
wlan_setup_rates_from_bssdesc(mlan_private * pmpriv,BSSDescriptor_t * pbss_desc,t_u8 * pout_rates,t_u32 * pout_rates_size)262 mlan_status wlan_setup_rates_from_bssdesc(mlan_private *pmpriv,
263 BSSDescriptor_t *pbss_desc,
264 t_u8 *pout_rates,
265 t_u32 *pout_rates_size)
266 {
267 t_u8 card_rates[WLAN_SUPPORTED_RATES] = {0};
268 t_u32 card_rates_size = 0;
269 ENTER();
270 /* Copy AP supported rates */
271 (void)__memcpy(pmpriv->adapter, pout_rates, pbss_desc->supported_rates, WLAN_SUPPORTED_RATES);
272
273 if ((pmpriv->adapter->region_code == COUNTRY_CODE_JP_40 || pmpriv->adapter->region_code == COUNTRY_CODE_JP_FF) &&
274 (pbss_desc->phy_param_set.ds_param_set.current_chan == 14))
275 {
276 /* Special Case: For Japan, 11G rates on CH14 are not allowed*/
277 card_rates_size = wlan_get_supported_rates(pmpriv, pmpriv->bss_mode, BAND_B, card_rates);
278 }
279 else
280 {
281 /* Get the STA supported rates */
282 card_rates_size = wlan_get_supported_rates(pmpriv, pmpriv->bss_mode, pmpriv->config_bands, card_rates);
283 }
284 /* Get the common rates between AP and STA supported rates */
285 if (wlan_get_common_rates(pmpriv, pout_rates, WLAN_SUPPORTED_RATES, card_rates, card_rates_size))
286 {
287 *pout_rates_size = 0;
288 PRINTM(MERROR, "wlan_get_common_rates failed\n");
289 LEAVE();
290 return MLAN_STATUS_FAILURE;
291 }
292
293 *pout_rates_size = MIN(wlan_strlen((char *)pout_rates), WLAN_SUPPORTED_RATES);
294
295 LEAVE();
296 return MLAN_STATUS_SUCCESS;
297 }
298
299 #if !CONFIG_WIFI_NM_WPA_SUPPLICANT
300 /**
301 * @brief This function updates RSN IE in the association request.
302 *
303 * @param pmpriv A pointer to mlan_private structure
304 *
305 * @param ptlv_rsn_ie A pointer to rsn_ie TLV
306 */
wlan_update_rsn_ie(mlan_private * pmpriv,MrvlIEtypes_RsnParamSet_t * ptlv_rsn_ie,t_u16 * rsn_ie_len,t_u8 * akm_type)307 static int wlan_update_rsn_ie(mlan_private *pmpriv,
308 MrvlIEtypes_RsnParamSet_t *ptlv_rsn_ie,
309 t_u16 *rsn_ie_len,
310 t_u8 *akm_type)
311 {
312 t_u16 *prsn_cap;
313 t_u8 *ptr;
314 t_u8 *pairwise_cipher_count_ptr;
315 t_u8 *group_mgmt_cipher_suite_ptr = MNULL;
316 t_u8 *pmkid_list_ptr = MNULL;
317 t_u8 *end_ptr;
318 t_u16 pmf_mask = 0x00;
319 t_u16 pairwise_cipher_count = 0;
320 t_u16 akm_suite_count = 0;
321 t_u16 pmkid_count = 0;
322 t_u8 i;
323
324 #define PREFERENCE_TKIP 1
325 /* Cipher Perference Order:
326 (5) CIPHER_SYITE_TYPE_GCMP_256 = 9
327 (4) CIPHER_SYITE_TYPE_GCMP_128 = 8
328 (3) CIPHER_SYITE_TYPE_CCMP_256 = 10
329 (2) CIPHER_SYITE_TYPE_CCMP_128 = 4
330 (1) CIPHER_SYITE_TYPE_TKIP = 2
331 (0) Skip
332 */
333 t_u8 preference_selected;
334 t_u8 cipher_selected_id;
335 #if CONFIG_WPA_SUPP
336 t_u8 cipher_preference[11] = {0, 0, 1, 0, 2, 0, 0, 0, 4, 5, 3};
337 #else
338 t_u8 cipher_preference[5] = {0, 0, 1, 0, 2};
339 #endif
340 t_u8 oui[4] = {0x00, 0x0f, 0xac, 0x00};
341
342 /* AKM Perference Order:
343 (13) AKM_SUITE_TYPE_SAE_EXT_KEY = 24
344 (12) AKM_SUITE_TYPE_1X_SUITEB_FT_SHA384 = 13
345 (11) AKM_SUITE_TYPE_1X_SUITEB_SHA384 = 12
346 (10) AKM_SUITE_TYPE_1X_SUITEB_SHA256 = 11
347 (9) AKM_SUITE_TYPE_1X_FT = 3
348 (8) AKM_SUITE_TYPE_1X_SHA256 = 5
349 (7) AKM_SUITE_TYPE_1X = 1
350 (6) AKM_SUITE_TYPE_FT_SAE = 9 //Not supported in esupp
351 (5) AKM_SUITE_TYPE_SAE = 8
352 (4) AKM_SUITE_TYPE_OWE = 18
353 (3) AKM_SUITE_TYPE_FT_PSK = 4 //Not supported in esupp
354 (2) AKM_SUITE_TYPE_PSK_SHA256 = 6
355 (1) AKM_SUITE_TYPE_PSK = 2
356 (0) Skip
357 */
358 t_u8 akm_type_selected;
359 t_u8 akm_type_id = 0;
360 #if CONFIG_11R
361 t_u8 akm_preference[25] = {0, 7, 1, 9, 3, 8, 2, 0, 5, 6, 0, 10, 11, 12, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 13};
362 #else
363 t_u8 akm_preference[25] = {0, 7, 1, 0, 0, 8, 2, 0, 5, 0, 0, 10, 11, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 13};
364 #endif
365
366 int ap_mfpc = 0, ap_mfpr = 0, ret = MLAN_STATUS_SUCCESS;
367
368 pmf_mask = (((pmpriv->pmfcfg.mfpc << MFPC_BIT) | (pmpriv->pmfcfg.mfpr << MFPR_BIT)) | (~PMF_MASK));
369 /* prsn_cap = prsn_ie->rsn_ie + 2 bytes version + 4 bytes
370 * group_cipher_suite + 2 bytes pairwise_cipher_count +
371 * pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN + 2 bytes
372 * akm_suite_count + akm_suite_count * AKM_SUITE_LEN
373 */
374 end_ptr = ptlv_rsn_ie->rsn_ie + *rsn_ie_len;
375
376 ptr = ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8);
377
378 pairwise_cipher_count_ptr = ptr;
379 pairwise_cipher_count = wlan_le16_to_cpu(*(t_u16 *)ptr);
380 ptr += sizeof(t_u16);
381
382 preference_selected = 0;
383 cipher_selected_id = 0;
384 for (i = 0; i < pairwise_cipher_count; i++)
385 {
386 if ((ptr[3] < sizeof(cipher_preference)) && (cipher_preference[ptr[3]] > preference_selected))
387 {
388 preference_selected = cipher_preference[ptr[3]];
389 cipher_selected_id = ptr[3];
390 }
391 ptr += PAIRWISE_CIPHER_SUITE_LEN;
392 }
393
394 if (preference_selected == 0)
395 {
396 PRINTM(MERROR, "RSNE: PAIRWISE_CIPHER not supported\n");
397 return MLAN_STATUS_FAILURE;
398 }
399 if ((preference_selected == PREFERENCE_TKIP) && ((*akm_type == AssocAgentAuth_Wpa3Sae)
400 #if CONFIG_DRIVER_OWE
401 || (*akm_type == AssocAgentAuth_Owe)))
402 {
403 #else
404 ))
405 {
406 #endif
407 PRINTM(MERROR, "RSNE: PAIRWISE_CIPHER TKIP not allowed for AKM %s\n",
408 (*akm_type == AssocAgentAuth_Wpa3Sae) ? "SAE" : "OWE");
409 return MLAN_STATUS_FAILURE;
410 }
411 if ((preference_selected == PREFERENCE_TKIP) && (*akm_type == AssocAgentAuth_Auto))
412 {
413 *akm_type = AssocAgentAuth_Open;
414 }
415 /* Process AKM
416 * Preference order for AssocAgentAuth_Auto:
417 * FT Authentication using SAE 00-0F-AC:9 (not supported in embedded supplicant)
418 * SAE Authentication 00-0F-AC:8
419 * OWE Authentication 00-0F-AC:18
420 * FT Authentication using PSK 00-0F-AC:4 (not supported in embedded supplicant)
421 * PSK using SHA-256 00-0F-AC:6
422 * PSK 00-0F-AC:2
423 */
424 ptr = ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8) + sizeof(t_u16) +
425 pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN;
426 akm_suite_count = wlan_le16_to_cpu(*(t_u16 *)ptr);
427 ptr += sizeof(t_u16); // move pointer to AKM suite
428
429 akm_type_selected = 0;
430
431 if (*akm_type == AssocAgentAuth_Auto)
432 {
433 // find the best one
434 for (i = 0; i < akm_suite_count; i++)
435 {
436 if ((ptr[3] < sizeof(akm_preference)) && (akm_preference[ptr[3]] > akm_type_selected))
437 {
438 akm_type_selected = akm_preference[ptr[3]];
439 akm_type_id = ptr[3];
440 }
441 ptr += AKM_SUITE_LEN;
442 }
443 if (akm_type_selected)
444 {
445 if (akm_type_id == 6)
446 {
447 *akm_type = AssocAgentAuth_Open;
448 }
449 else if (akm_type_id == 1)
450 {
451 *akm_type = AssocAgentAuth_Open;
452 }
453 else if (akm_type_id == 3)
454 {
455 *akm_type = AssocAgentAuth_Open;
456 }
457 else if (akm_type_id == 5)
458 {
459 *akm_type = AssocAgentAuth_Open;
460 }
461 else if (akm_type_id == 11)
462 {
463 *akm_type = AssocAgentAuth_Open;
464 }
465 else if (akm_type_id == 12)
466 {
467 *akm_type = AssocAgentAuth_Open;
468 }
469 else if (akm_type_id == 13)
470 {
471 *akm_type = AssocAgentAuth_Open;
472 }
473 else if (akm_type_id == 2)
474 {
475 *akm_type = AssocAgentAuth_Open;
476 }
477 #if CONFIG_11R
478 else if (akm_type_id == 4)
479 {
480 *akm_type = AssocAgentAuth_FastBss;
481 }
482 #endif
483 #if CONFIG_DRIVER_OWE
484 else if (akm_type_id == 18)
485 {
486 *akm_type = AssocAgentAuth_Owe;
487 }
488 #endif
489 else if (akm_type_id == 8 || akm_type_id == 24)
490 {
491 *akm_type = AssocAgentAuth_Wpa3Sae;
492 }
493 #if CONFIG_11R
494 else if (akm_type_id == 9)
495 {
496 *akm_type = AssocAgentAuth_FastBss_SAE;
497 }
498 #endif
499 }
500 }
501 else
502 {
503 // find the matched AKM
504
505 for (i = 0; i < akm_suite_count; i++)
506 {
507 if (ptr[3] < sizeof(akm_preference))
508 {
509 #if CONFIG_11R
510 if ((*akm_type == AssocAgentAuth_FastBss_Skip) && (ptr[3] == 13))
511 {
512 break;
513 }
514 else
515 #endif
516 if ((*akm_type == AssocAgentAuth_Open) && (ptr[3] == 12))
517 {
518 break;
519 }
520 else if ((*akm_type == AssocAgentAuth_Open) && (ptr[3] == 11))
521 {
522 break;
523 }
524 #if CONFIG_11R
525 else if ((*akm_type == AssocAgentAuth_FastBss_Skip) && (ptr[3] == 3))
526 {
527 break;
528 }
529 #endif
530 else if ((*akm_type == AssocAgentAuth_Open) && (ptr[3] == 5))
531 {
532 break;
533 }
534 else if ((*akm_type == AssocAgentAuth_Open) && (ptr[3] == 1))
535 {
536 break;
537 }
538 #if CONFIG_11R
539 else if ((*akm_type == AssocAgentAuth_FastBss_Skip) && (ptr[3] == 9))
540 {
541 break;
542 }
543 #endif
544 else if ((*akm_type == AssocAgentAuth_Wpa3Sae) && (ptr[3] == 8 || ptr[3] == 24))
545 {
546 break;
547 }
548 #if CONFIG_DRIVER_OWE
549 else if ((*akm_type == AssocAgentAuth_Owe) && (ptr[3] == 18))
550 {
551 break;
552 }
553 #endif
554 #if CONFIG_11R
555 else if ((*akm_type == AssocAgentAuth_FastBss_Skip) && (ptr[3] == 4))
556 {
557 break;
558 }
559 #endif
560 if ((*akm_type == AssocAgentAuth_Open) && (ptr[3] == 6))
561 {
562 break;
563 }
564 else if ((*akm_type == AssocAgentAuth_Open) && (ptr[3] == 2))
565 {
566 break;
567 }
568 }
569 ptr += AKM_SUITE_LEN;
570 }
571 if (i == akm_suite_count)
572 {
573 akm_type_selected = 0; // not found
574 }
575 else
576 {
577 akm_type_selected = akm_preference[ptr[3]];
578 akm_type_id = ptr[3];
579 }
580 }
581 if (akm_type_selected == 0)
582 {
583 PRINTM(MERROR, "RSNE: AKM Suite not found for authtype %d\n", *akm_type);
584 return MLAN_STATUS_FAILURE;
585 }
586 /* Process RSNCAP */
587 ptr = ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8) + sizeof(t_u16) +
588 pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN + sizeof(t_u16) + akm_suite_count * AKM_SUITE_LEN;
589 prsn_cap = (t_u16 *)ptr;
590
591 ap_mfpc = ((*prsn_cap & (0x1 << MFPC_BIT)) == (0x1 << MFPC_BIT));
592 ap_mfpr = ((*prsn_cap & (0x1 << MFPR_BIT)) == (0x1 << MFPR_BIT));
593
594 if ((!ap_mfpc && !ap_mfpr && pmpriv->pmfcfg.mfpr) || ((!ap_mfpc) && ap_mfpr) ||
595 (ap_mfpc && ap_mfpr && (!pmpriv->pmfcfg.mfpc)))
596 {
597 PRINTM(MERROR, "RSNE: Mismatch in PMF config of STA and AP, can't associate to AP\n");
598 return MLAN_STATUS_FAILURE;
599 }
600 *prsn_cap |= PMF_MASK;
601 *prsn_cap &= pmf_mask;
602
603 // PMKID
604 ptr += sizeof(t_u16);
605 if (end_ptr >= (ptr + 2))
606 {
607 pmkid_count = wlan_le16_to_cpu(*(t_u16 *)ptr);
608 ptr += sizeof(t_u16);
609 pmkid_list_ptr = ptr;
610 ptr += pmkid_count * PMKID_LEN;
611 }
612 // Group Mgmt Cipher Suite
613 if ((end_ptr >= (ptr + 4)) && (pmf_mask & PMF_MASK))
614 {
615 group_mgmt_cipher_suite_ptr = ptr;
616 }
617 /* Compose new RSNE */
618 // pairwiase
619 ptr = pairwise_cipher_count_ptr;
620 *(t_u16 *)ptr = wlan_cpu_to_le16(1);
621 ptr += sizeof(t_u16);
622 oui[3] = cipher_selected_id;
623 *(t_u32 *)ptr = *(t_u32 *)oui;
624 ptr += PAIRWISE_CIPHER_SUITE_LEN;
625 // akm
626 *(t_u16 *)ptr = wlan_cpu_to_le16(1);
627 ptr += sizeof(t_u16);
628 oui[3] = akm_type_id;
629 *(t_u32 *)ptr = *(t_u32 *)oui;
630 ptr += AKM_SUITE_LEN;
631 // RSNCAP
632 *(t_u16 *)ptr = wlan_cpu_to_le16(*prsn_cap);
633 ptr += sizeof(t_u16);
634 // PMKID list
635 if (pmkid_list_ptr || group_mgmt_cipher_suite_ptr)
636 {
637 // Add PMKID
638 *(t_u16 *)ptr = wlan_cpu_to_le16(pmkid_count);
639 ptr += sizeof(t_u16);
640 if (pmkid_count)
641 {
642 (void)memmove(ptr, (t_u8 *)pmkid_list_ptr, (end_ptr - ptr));
643 ptr += pmkid_count * PMKID_LEN;
644 }
645 if (group_mgmt_cipher_suite_ptr)
646 {
647 // Add Group Mgmt Cipher Suite
648 (void)memmove(ptr, (t_u8 *)group_mgmt_cipher_suite_ptr, (end_ptr - ptr));
649 ptr += GROUP_MGMT_CIPHER_SUITE_LEN;
650 }
651 }
652 *rsn_ie_len = ptr - ptlv_rsn_ie->rsn_ie;
653 return ret;
654 }
655 #endif
656
657 #if CONFIG_11R
658 /**
659 * @brief This function is to find FT AKM in RSN.
660 *
661 * @param pmpriv A pointer to mlan_private structure
662 *
663 * @param rsn_ie A pointer to rsn_ie
664 *
665 * @return 1 when FT AKM is in RSN, otherwise 0
666 */
667 t_u8 wlan_ft_akm_is_used(mlan_private *pmpriv, t_u8 *rsn_ie)
668 {
669 t_u8 *temp;
670 t_u16 count;
671 t_u16 pairwise_cipher_count = 0;
672 t_u16 akm_suite_count = 0;
673 t_u8 found = 0;
674 t_u8 rsn_ft_1x_oui[4] = {0x00, 0x0f, 0xac, 0x03};
675 t_u8 rsn_ft_psk_oui[4] = {0x00, 0x0f, 0xac, 0x04};
676 t_u8 rsn_ft_sae_oui[4] = {0x00, 0x0f, 0xac, 0x09};
677 t_u8 rsn_ft_1x_sha384_oui[4] = {0x00, 0x0f, 0xac, 0x0d};
678
679 ENTER();
680
681 if (rsn_ie == MNULL)
682 {
683 goto done;
684 }
685 else
686 {
687 /* Do nothing */
688 }
689
690 if (rsn_ie[0] != (t_u8)RSN_IE)
691 {
692 goto done;
693 }
694 else
695 {
696 /* Do nothing */
697 }
698
699 /* 4 bytes header + 2 bytes version + 4 bytes group_cipher_suite +
700 * 2 bytes pairwise_cipher_count + pairwise_cipher_count *
701 * PAIRWISE_CIPHER_SUITE_LEN (4) + 2 bytes akm_suite_count +
702 * akm_suite_count * AKM_SUITE_LEN (4)
703 */
704 count = *(t_u16 *)(void *)(rsn_ie + 4 + 2 + 4 * (int)sizeof(t_u8));
705 pairwise_cipher_count = wlan_le16_to_cpu(count);
706 count = *(t_u16 *)(void *)(rsn_ie + 4 + 2 + 4 * (int)sizeof(t_u8) + (int)sizeof(t_u16) +
707 (int)pairwise_cipher_count * 4);
708 akm_suite_count = (t_u16)wlan_le16_to_cpu(count);
709 temp = (t_u8 *)(rsn_ie + 4 + sizeof(t_u16) + 4 * (int)sizeof(t_u8) + (int)sizeof(t_u16) +
710 (int)pairwise_cipher_count * 4 + sizeof(t_u16));
711
712 while (akm_suite_count > 0U)
713 {
714 if (__memcmp(pmpriv->adapter, temp, rsn_ft_1x_oui, sizeof(rsn_ft_1x_oui)) == 0 ||
715 __memcmp(pmpriv->adapter, temp, rsn_ft_psk_oui, sizeof(rsn_ft_psk_oui)) == 0 ||
716 __memcmp(pmpriv->adapter, temp, rsn_ft_sae_oui, sizeof(rsn_ft_sae_oui)) == 0 ||
717 __memcmp(pmpriv->adapter, temp, rsn_ft_1x_sha384_oui, sizeof(rsn_ft_1x_sha384_oui)) == 0)
718 {
719 found = 1;
720 break;
721 }
722 temp += 4;
723 akm_suite_count--;
724 }
725
726 done:
727 LEAVE();
728 return found;
729 }
730
731 /**
732 * @brief Append IE as a pass through TLV to a TLV buffer.
733 *
734 * This routine appends IE as a pass through TLV type to the request.
735 *
736 * @param priv A pointer to mlan_private structure
737 * @param ie A pointer to IE buffer
738 * @param ppbuffer pointer to command buffer pointer
739 *
740 * @return bytes added to the buffer
741 */
742 static int wlan_cmd_append_pass_through_ie(mlan_private *priv, IEEEtypes_Generic_t *ie, t_u8 **ppbuffer)
743 {
744 int ret_len = 0;
745 MrvlIEtypesHeader_t ie_header;
746
747 ENTER();
748
749 /* Null Checks */
750 if (ppbuffer == MNULL)
751 {
752 LEAVE();
753 return 0;
754 }
755 if (*ppbuffer == MNULL)
756 {
757 LEAVE();
758 return 0;
759 }
760 if (ie->ieee_hdr.len)
761 {
762 PRINTM(MINFO, "append generic IE %d to %p\n", ie->ieee_hdr.len, *ppbuffer);
763
764 /* Wrap the generic IE buffer with a pass through TLV type */
765 ie_header.type = wlan_cpu_to_le16(TLV_TYPE_PASSTHROUGH);
766 ie_header.len = wlan_cpu_to_le16(ie->ieee_hdr.len + sizeof(IEEEtypes_Header_t));
767 __memcpy(priv->adapter, *ppbuffer, &ie_header, sizeof(ie_header));
768
769 /* Increment the return size and the return buffer pointer param
770 */
771 *ppbuffer += sizeof(ie_header);
772 ret_len += sizeof(ie_header);
773
774 /* Copy the generic IE buffer to the output buffer, advance
775 * pointer */
776 __memcpy(priv->adapter, *ppbuffer, ie, ie->ieee_hdr.len + sizeof(IEEEtypes_Header_t));
777
778 /* Increment the return size and the return buffer pointer param
779 */
780 *ppbuffer += ie->ieee_hdr.len + sizeof(IEEEtypes_Header_t);
781 ret_len += ie->ieee_hdr.len + sizeof(IEEEtypes_Header_t);
782 }
783 /* return the length appended to the buffer */
784 LEAVE();
785 return ret_len;
786 }
787 #endif
788
789 /********************************************************
790 Global Functions
791 ********************************************************/
792 /**
793 * @brief This function prepares command of association.
794 *
795 * @param pmpriv A pointer to mlan_private structure
796 * @param cmd A pointer to HostCmd_DS_COMMAND structure
797 * @param pdata_buf A pointer cast of BSSDescriptor_t from the
798 * scan table to assoc
799 *
800 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
801 */
802 mlan_status wlan_cmd_802_11_associate(IN mlan_private *pmpriv, IN HostCmd_DS_COMMAND *cmd, IN t_void *pdata_buf)
803 {
804 mlan_status ret = MLAN_STATUS_SUCCESS;
805 mlan_adapter *pmadapter = pmpriv->adapter;
806 HostCmd_DS_802_11_ASSOCIATE *passo = &cmd->params.associate;
807 BSSDescriptor_t *pbss_desc;
808 MrvlIEtypes_SsIdParamSet_t *pssid_tlv;
809 MrvlIEtypes_PhyParamSet_t *pphy_tlv;
810 MrvlIEtypes_SsParamSet_t *pss_tlv;
811 MrvlIEtypes_RatesParamSet_t *prates_tlv;
812 MrvlIEtypes_AuthType_t *pauth_tlv = MNULL;
813 MrvlIEtypes_RsnParamSet_t *prsn_ie_tlv = MNULL;
814 MrvlIEtypes_ChanListParamSet_t *pchan_tlv;
815 WLAN_802_11_RATES rates = {0x00};
816 t_u32 rates_size;
817 t_u16 tmp_cap;
818 t_u8 *pos, *auth_pos = NULL;
819 t_u8 akm_type = 0;
820 #if !CONFIG_WIFI_NM_WPA_SUPPLICANT
821 #if CONFIG_11R
822 t_u8 ft_akm = 0;
823 #endif
824 #endif
825 MrvlIEtypes_PrevBssid_t *prev_bssid_tlv = MNULL;
826 t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = {0};
827 #if CONFIG_DRIVER_MBO
828 t_u8 oper_class = 1;
829 #endif
830
831 #if CONFIG_HOST_MLME
832 MrvlIEtypes_HostMlme_t *host_mlme_tlv = MNULL;
833 #endif
834
835 ENTER();
836
837 (void)__memset(pmadapter, &rates, 0x00, sizeof(WLAN_802_11_RATES));
838 pbss_desc = (BSSDescriptor_t *)pdata_buf;
839 pos = (t_u8 *)&cmd->params;
840
841 cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE);
842
843 /* Save so we know which BSS Desc to use in the response handler */
844 pmpriv->pattempted_bss_desc = pbss_desc;
845 #if CONFIG_HOST_MLME
846 (void)__memcpy(pmadapter, &pmpriv->curr_bss_params.attemp_bssid, pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH);
847 pmpriv->assoc_req_size = 0;
848 #endif
849
850 (void)__memcpy(pmadapter, passo->peer_sta_addr, pbss_desc->mac_address, sizeof(passo->peer_sta_addr));
851
852 /* fixme: Look at this value carefully later. The listen interval is given to AP during
853 * this assoc. The listen_interval set later during IEEE PS should not (?) exceed this
854 */
855 /* Set the listen interval */
856 passo->listen_interval = wlan_cpu_to_le16(pmpriv->listen_interval);
857 /* Set the beacon period */
858 passo->beacon_period = wlan_cpu_to_le16(pbss_desc->beacon_period);
859
860 pos = (t_u8 *)cmd + S_DS_GEN + sizeof(HostCmd_DS_802_11_ASSOCIATE);
861 pssid_tlv = (MrvlIEtypes_SsIdParamSet_t *)(void *)pos;
862 pssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SSID);
863 pssid_tlv->header.len = (t_u16)pbss_desc->ssid.ssid_len;
864 (void)__memcpy(pmadapter, pssid_tlv->ssid, pbss_desc->ssid.ssid, pssid_tlv->header.len);
865 pos += sizeof(pssid_tlv->header) + pssid_tlv->header.len;
866 pssid_tlv->header.len = wlan_cpu_to_le16(pssid_tlv->header.len);
867
868 pphy_tlv = (MrvlIEtypes_PhyParamSet_t *)(void *)pos;
869 pphy_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_PHY_DS);
870 pphy_tlv->header.len = sizeof(pphy_tlv->fh_ds.ds_param_set);
871 (void)__memcpy(pmadapter, &pphy_tlv->fh_ds.ds_param_set, &pbss_desc->phy_param_set.ds_param_set.current_chan,
872 sizeof(pphy_tlv->fh_ds.ds_param_set));
873 pos += sizeof(pphy_tlv->header) + pphy_tlv->header.len;
874 pphy_tlv->header.len = wlan_cpu_to_le16(pphy_tlv->header.len);
875
876 pss_tlv = (MrvlIEtypes_SsParamSet_t *)(void *)pos;
877 pss_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CF);
878 pss_tlv->header.len = sizeof(pss_tlv->cf_ibss.cf_param_set);
879 pos += sizeof(pss_tlv->header) + pss_tlv->header.len;
880 pss_tlv->header.len = wlan_cpu_to_le16(pss_tlv->header.len);
881
882 /* Get the common rates supported between the driver and the BSS Desc */
883 if (wlan_setup_rates_from_bssdesc(pmpriv, pbss_desc, rates, &rates_size) != MLAN_STATUS_SUCCESS)
884 {
885 ret = MLAN_STATUS_FAILURE;
886 goto done;
887 }
888
889 /* Save the data rates into Current BSS state structure */
890 pmpriv->curr_bss_params.num_of_rates = rates_size;
891 (void)__memcpy(pmadapter, &pmpriv->curr_bss_params.data_rates, rates, rates_size);
892
893 /* Setup the Rates TLV in the association command */
894 prates_tlv = (MrvlIEtypes_RatesParamSet_t *)(void *)pos;
895 prates_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_RATES);
896 prates_tlv->header.len = wlan_cpu_to_le16((t_u16)rates_size);
897 (void)__memcpy(pmadapter, prates_tlv->rates, rates, rates_size);
898 pos += sizeof(prates_tlv->header) + rates_size;
899 PRINTM(MINFO, "ASSOC_CMD: Rates size = %d\n", rates_size);
900
901 /* Add the Authentication type to be used for Auth frames if needed */
902 if ((pmpriv->sec_info.authentication_mode != MLAN_AUTH_MODE_AUTO)
903 #if CONFIG_DRIVER_OWE
904 || (pbss_desc->owe_transition_mode == OWE_TRANS_MODE_OWE)
905 #endif
906 )
907 {
908 pauth_tlv = (MrvlIEtypes_AuthType_t *)(void *)pos;
909 pauth_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_AUTH_TYPE);
910 pauth_tlv->header.len = sizeof(pauth_tlv->auth_type);
911 if (pmpriv->sec_info.authentication_mode == MLAN_AUTH_MODE_SAE)
912 {
913 pauth_tlv->auth_type = wlan_cpu_to_le16((t_u16)AssocAgentAuth_Wpa3Sae);
914 }
915 #if CONFIG_11R
916 else if (pmpriv->sec_info.authentication_mode == MLAN_AUTH_MODE_FT)
917 {
918 #if CONFIG_HOST_MLME
919 if (pmpriv->curr_bss_params.host_mlme)
920 {
921 pauth_tlv->auth_type = wlan_cpu_to_le16(AssocAgentAuth_FastBss_Skip);
922 }
923 else
924 #endif
925 {
926 pauth_tlv->auth_type = wlan_cpu_to_le16(AssocAgentAuth_FastBss);
927 }
928 }
929 #endif
930 #if CONFIG_DRIVER_OWE
931 else if (
932 #if CONFIG_HOST_MLME
933 !pmpriv->curr_bss_params.host_mlme &&
934 #endif
935 ((pbss_desc->owe_transition_mode == OWE_TRANS_MODE_OWE) ||
936 (pmpriv->sec_info.authentication_mode == MLAN_AUTH_MODE_OWE)))
937 {
938 pauth_tlv->auth_type = wlan_cpu_to_le16((t_u16)AssocAgentAuth_Owe);
939 }
940 #endif
941 else if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled)
942 {
943 pauth_tlv->auth_type = wlan_cpu_to_le16((t_u16)pmpriv->sec_info.authentication_mode);
944 }
945 else
946 {
947 pauth_tlv->auth_type = wlan_cpu_to_le16(MLAN_AUTH_MODE_OPEN);
948 }
949 pos += sizeof(pauth_tlv->header) + pauth_tlv->header.len;
950 pauth_tlv->header.len = wlan_cpu_to_le16(pauth_tlv->header.len);
951 }
952
953 if (IS_SUPPORT_MULTI_BANDS(pmadapter) && (pbss_desc->bss_band & pmpriv->config_bands) &&
954 !(ISSUPP_11NENABLED(pmadapter->fw_cap_info) && (!pbss_desc->disable_11n) &&
955 (pmpriv->config_bands & BAND_GN || pmpriv->config_bands & BAND_AN) && (pbss_desc->pht_cap != MNULL)))
956 {
957 /* Append a channel TLV for the channel the attempted AP was found on */
958 pchan_tlv = (MrvlIEtypes_ChanListParamSet_t *)(void *)pos;
959 pchan_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
960 pchan_tlv->header.len = wlan_cpu_to_le16(sizeof(ChanScanParamSet_t));
961
962 (void)__memset(pmadapter, pchan_tlv->chan_scan_param, 0x00, sizeof(ChanScanParamSet_t));
963 pchan_tlv->chan_scan_param[0].chan_number = (pbss_desc->phy_param_set.ds_param_set.current_chan);
964 PRINTM(MINFO, "Assoc: TLV Chan = %d\n", pchan_tlv->chan_scan_param[0].chan_number);
965
966 pchan_tlv->chan_scan_param[0].radio_type = wlan_band_to_radio_type((t_u8)pbss_desc->bss_band);
967
968 PRINTM(MINFO, "Assoc: TLV Band = %d\n", pchan_tlv->chan_scan_param[0].radio_type);
969 pos += sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
970 }
971
972 #if CONFIG_WPA_SUPP
973 #if CONFIG_WPA_SUPP_WPS
974 if (pmpriv->wps.session_enable == MFALSE)
975 {
976 #endif /* CONFIG_WPA_SUPP_WPS */
977 #elif (CONFIG_WPS2)
978 if (wlan_get_prov_session() != PROV_WPS_SESSION_ATTEMPT)
979 {
980 #endif
981 /* fixme: The above 'if' is used instead of below 'if' for now since
982 WPS module is mlan integrated yet. Fix after it is done.
983 */
984 /* if (!pmpriv->wps.session_enable) { */
985 if ((pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.wpa2_enabled)
986 #if CONFIG_DRIVER_OWE
987 || (pbss_desc->owe_transition_mode == OWE_TRANS_MODE_OWE) ||
988 (pmpriv->sec_info.authentication_mode == MLAN_AUTH_MODE_OWE)
989 #endif
990 )
991 {
992 if ((pauth_tlv == MNULL) && (pmpriv->sec_info.authentication_mode == MLAN_AUTH_MODE_AUTO))
993 {
994 auth_pos = pos;
995 pos += sizeof(MrvlIEtypes_AuthType_t);
996 }
997
998 prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)(void *)pos;
999 prsn_ie_tlv->header.type = (t_u16)pmpriv->wpa_ie[0]; /* WPA_IE
1000 or
1001 RSN_IE
1002 */
1003 prsn_ie_tlv->header.type = prsn_ie_tlv->header.type & 0x00FF;
1004 prsn_ie_tlv->header.type = wlan_cpu_to_le16(prsn_ie_tlv->header.type);
1005 prsn_ie_tlv->header.len = (t_u16)pmpriv->wpa_ie[1];
1006 prsn_ie_tlv->header.len = prsn_ie_tlv->header.len & 0x00FF;
1007 if (prsn_ie_tlv->header.len <= (sizeof(pmpriv->wpa_ie) - 2))
1008 {
1009 (void)__memcpy(pmadapter, prsn_ie_tlv->rsn_ie, &pmpriv->wpa_ie[2], prsn_ie_tlv->header.len);
1010 #if !CONFIG_WIFI_NM_WPA_SUPPLICANT
1011 if (pmpriv->sec_info.wpa2_enabled
1012 #if CONFIG_WPA_SUPP_DPP
1013 && pmpriv->is_dpp_connect == MFALSE
1014 #endif
1015 )
1016 {
1017 akm_type = pauth_tlv ? wlan_le16_to_cpu(pauth_tlv->auth_type) : AssocAgentAuth_Auto;
1018 t_u16 rsn_ie_tlv_len = prsn_ie_tlv->header.len;
1019 ret = (mlan_status)wlan_update_rsn_ie(pmpriv, prsn_ie_tlv, &rsn_ie_tlv_len, &akm_type);
1020 prsn_ie_tlv->header.len = rsn_ie_tlv_len;
1021 #if CONFIG_11R
1022 /** parse rsn ie to find whether ft akm is used*/
1023 ft_akm = wlan_ft_akm_is_used(pmpriv, (t_u8 *)prsn_ie_tlv);
1024 #endif
1025 }
1026 #endif
1027 }
1028 else
1029 {
1030 ret = MLAN_STATUS_FAILURE;
1031 goto done;
1032 }
1033 HEXDUMP("ASSOC_CMD: RSN IE", (t_u8 *)prsn_ie_tlv, sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len);
1034 pos += sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len;
1035 prsn_ie_tlv->header.len = wlan_cpu_to_le16(prsn_ie_tlv->header.len);
1036
1037 #if CONFIG_11R
1038 if ((akm_type == AssocAgentAuth_FastBss) && (pmpriv->sec_info.is_ft == false))
1039 {
1040 akm_type = AssocAgentAuth_Open;
1041 }
1042 if ((akm_type == AssocAgentAuth_FastBss_SAE) && (pmpriv->sec_info.is_ft == false))
1043 {
1044 akm_type = AssocAgentAuth_Wpa3Sae;
1045 }
1046 #endif
1047 #if CONFIG_DRIVER_OWE
1048 if ((akm_type == AssocAgentAuth_Owe) && (pmpriv->curr_bss_params.host_mlme))
1049 {
1050 akm_type = AssocAgentAuth_Open;
1051 }
1052 #endif
1053 if ((pauth_tlv == MNULL) && (pmpriv->sec_info.authentication_mode == MLAN_AUTH_MODE_AUTO))
1054 {
1055 pauth_tlv = (MrvlIEtypes_AuthType_t *)auth_pos;
1056 pauth_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_AUTH_TYPE);
1057 pauth_tlv->header.len = sizeof(pauth_tlv->auth_type);
1058 pauth_tlv->auth_type = wlan_cpu_to_le16(akm_type);
1059
1060 pauth_tlv->header.len = wlan_cpu_to_le16(pauth_tlv->header.len);
1061 }
1062 }
1063 #if CONFIG_WPA_SUPP
1064 #if CONFIG_WPA_SUPP_WPS
1065 }
1066 #endif /* CONFIG_WPA_SUPP_WPS */
1067 #elif (CONFIG_WPS2)
1068 }
1069 #endif
1070
1071 if ((pauth_tlv != MNULL) && (pauth_tlv->auth_type == wlan_cpu_to_le16(AssocAgentAuth_Wpa3Sae)))
1072 {
1073 if ((pbss_desc->prsnx_ie != MNULL) && pbss_desc->prsnx_ie->ieee_hdr.len &&
1074 (pbss_desc->prsnx_ie->data[0] & (0x1 << SAE_H2E_BIT)))
1075 {
1076 MrvlIEtypes_SAE_PWE_Mode_t *psae_pwe_mode_tlv;
1077
1078 /* Setup the sae mode TLV in the association command */
1079 psae_pwe_mode_tlv = (MrvlIEtypes_SAE_PWE_Mode_t *)(void *)pos;
1080 psae_pwe_mode_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_WPA3_SAE_PWE_DERIVATION_MODE);
1081 psae_pwe_mode_tlv->header.len = sizeof(psae_pwe_mode_tlv->pwe);
1082 psae_pwe_mode_tlv->pwe[0] = pbss_desc->prsnx_ie->data[0];
1083 pos += sizeof(psae_pwe_mode_tlv->header) + sizeof(psae_pwe_mode_tlv->pwe);
1084 }
1085 }
1086
1087 if (ISSUPP_11NENABLED(pmadapter->fw_cap_info) && (!pbss_desc->disable_11n) &&
1088 (pmpriv->config_bands & BAND_GN || pmpriv->config_bands & BAND_AN) && wmsdk_is_11N_enabled() &&
1089 (!pmpriv->sec_info.is_wpa_tkip))
1090 {
1091 (void)wlan_cmd_append_11n_tlv(pmpriv, pbss_desc, &pos);
1092 }
1093 else if (pmpriv->hotspot_cfg & HOTSPOT_ENABLED)
1094 {
1095 wlan_add_ext_capa_info_ie(pmpriv, pbss_desc, &pos);
1096 }
1097 else
1098 {
1099 /* Do nothing */
1100 }
1101
1102 #if CONFIG_11AC
1103 if (ISSUPP_11ACENABLED(pmadapter->fw_cap_info) && (!pbss_desc->disable_11n) &&
1104 wlan_11ac_bandconfig_allowed(pmpriv, pbss_desc->bss_band))
1105 {
1106 (void)wlan_cmd_append_11ac_tlv(pmpriv, pbss_desc, &pos);
1107 }
1108 #endif
1109
1110 #if CONFIG_11AX
1111 if ((IS_FW_SUPPORT_11AX(pmadapter)) && (!pbss_desc->disable_11n) &&
1112 wlan_11ax_bandconfig_allowed(pmpriv, pbss_desc->bss_band))
1113 wlan_cmd_append_11ax_tlv(pmpriv, pbss_desc, &pos);
1114 #endif
1115
1116 (void)wlan_wmm_process_association_req(pmpriv, &pos, &pbss_desc->wmm_ie, pbss_desc->pht_cap);
1117
1118 #if CONFIG_11R
1119 #if CONFIG_WPA_SUPP
1120 if (pmpriv->md_ie_len != 0U)
1121 #else
1122 if (ft_akm == 1U)
1123 #endif
1124 {
1125 wlan_cmd_append_pass_through_ie(pmpriv, (IEEEtypes_Generic_t *)(void *)pmpriv->md_ie, &pos);
1126 }
1127 else
1128 {
1129 /* Do nothing */
1130 }
1131 #endif
1132
1133 #if CONFIG_HOST_MLME
1134 if (pmpriv->curr_bss_params.host_mlme)
1135 {
1136 host_mlme_tlv = (MrvlIEtypes_HostMlme_t *)pos;
1137 host_mlme_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_HOST_MLME);
1138 host_mlme_tlv->header.len = wlan_cpu_to_le16(sizeof(host_mlme_tlv->host_mlme));
1139 host_mlme_tlv->host_mlme = MTRUE;
1140 pos += sizeof(host_mlme_tlv->header) + host_mlme_tlv->header.len;
1141 }
1142 #endif
1143 if (memcmp(&pmpriv->curr_bss_params.prev_bssid, zero_mac, MLAN_MAC_ADDR_LENGTH))
1144 {
1145 prev_bssid_tlv = (MrvlIEtypes_PrevBssid_t *)pos;
1146 prev_bssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_PREV_BSSID);
1147 prev_bssid_tlv->header.len = wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
1148 __memcpy(pmadapter, prev_bssid_tlv->prev_bssid, &pmpriv->curr_bss_params.prev_bssid, MLAN_MAC_ADDR_LENGTH);
1149 PRINTM(MCMND, "ASSOCIATE: PREV_BSSID = " MACSTR "\n", MAC2STR(pmpriv->curr_bss_params.prev_bssid));
1150 pos += sizeof(prev_bssid_tlv->header) + MLAN_MAC_ADDR_LENGTH;
1151 }
1152
1153 #if CONFIG_DRIVER_MBO
1154 wlan_get_curr_global_oper_class(pmpriv, pbss_desc->phy_param_set.ds_param_set.current_chan, BW_20MHZ, &oper_class);
1155 wlan_add_supported_oper_class_ie(pmpriv, &pos, oper_class);
1156 #endif
1157
1158 wlan_cmd_append_generic_ie(pmpriv, &pos);
1159
1160 cmd->size = wlan_cpu_to_le16((t_u16)(pos - (t_u8 *)passo) + S_DS_GEN);
1161
1162 /* Set the Capability info at last */
1163 (void)__memcpy(pmadapter, &tmp_cap, &pbss_desc->cap_info, sizeof(passo->cap_info));
1164
1165 if (pmpriv->config_bands == BAND_B)
1166 {
1167 SHORT_SLOT_TIME_DISABLED(tmp_cap);
1168 }
1169
1170 /* set SpectrumMgmt(BIT8) and RadioMeasurement(BIT12) if 11K is enabled
1171 */
1172
1173 #if CONFIG_11K_OFFLOAD
1174 if (pmpriv->enable_11k == (t_u8)1U)
1175 {
1176 SPECTRUM_MGMT_ENABLED(tmp_cap);
1177 RADIO_MEASUREMENT_ENABLED(tmp_cap);
1178 }
1179 else
1180 #endif
1181 #if CONFIG_11K
1182 if (pmpriv->enable_host_11k == (t_u8)1U)
1183 {
1184 SPECTRUM_MGMT_ENABLED(tmp_cap);
1185 RADIO_MEASUREMENT_ENABLED(tmp_cap);
1186 }
1187 else
1188 #endif
1189 {
1190 RADIO_MEASUREMENT_DISABLED(tmp_cap);
1191 }
1192
1193 tmp_cap &= CAPINFO_MASK;
1194 PRINTM(MINFO, "ASSOC_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n", tmp_cap, CAPINFO_MASK);
1195 tmp_cap = wlan_cpu_to_le16(tmp_cap);
1196 (void)__memcpy(pmadapter, &passo->cap_info, &tmp_cap, sizeof(passo->cap_info));
1197
1198 done:
1199
1200 LEAVE();
1201 return ret;
1202 }
1203
1204 /**
1205 * @brief Association firmware command response handler
1206 *
1207 * The response buffer for the association command has the following
1208 * memory layout.
1209 *
1210 * For cases where an association response was not received (indicated
1211 * by the CapInfo and AId field):
1212 *
1213 * .------------------------------------------------------------.
1214 * | Header(4 * sizeof(t_u16)): Standard command response hdr |
1215 * .------------------------------------------------------------.
1216 * | cap_info/Error Return(t_u16): |
1217 * | 0xFFFF(-1): Internal error for association |
1218 * | 0xFFFE(-2): Authentication unhandled message |
1219 * | 0xFFFD(-3): Authentication refused |
1220 * | 0xFFFC(-4): Timeout waiting for AP response |
1221 * | 0xFFFB(-5): Internal error for authentication |
1222 * .------------------------------------------------------------.
1223 * | status_code(t_u16): |
1224 * | If cap_info is -1: |
1225 * | An internal firmware failure prevented the |
1226 * | command from being processed. The status code |
1227 * | is 6 if associate response parameter invlaid, |
1228 * | 1 otherwise. |
1229 * | |
1230 * | If cap_info is -2: |
1231 * | An authentication frame was received but was |
1232 * | not handled by the firmware. IEEE Status code |
1233 * | for the failure is returned. |
1234 * | |
1235 * | If cap_info is -3: |
1236 * | An authentication frame was received and the |
1237 * | status_code is the IEEE Status reported in the |
1238 * | response. |
1239 * | |
1240 * | If cap_info is -4: |
1241 * | (1) Association response timeout |
1242 * | (2) Authentication response timeout |
1243 * | |
1244 * | If cap_info is -5: |
1245 * | An internal firmware failure prevented the |
1246 * | command from being processed. The status code |
1247 * | is 6 if authentication parameter invlaid, |
1248 * | 1 otherwise. |
1249 * .------------------------------------------------------------.
1250 * | a_id(t_u16): 0xFFFF |
1251 * .------------------------------------------------------------.
1252 *
1253 *
1254 * For cases where an association response was received, the IEEE
1255 * standard association response frame is returned:
1256 *
1257 * .------------------------------------------------------------.
1258 * | Header(4 * sizeof(t_u16)): Standard command response hdr |
1259 * .------------------------------------------------------------.
1260 * | cap_info(t_u16): IEEE Capability |
1261 * .------------------------------------------------------------.
1262 * | status_code(t_u16): IEEE Status Code |
1263 * .------------------------------------------------------------.
1264 * | a_id(t_u16): IEEE Association ID |
1265 * .------------------------------------------------------------.
1266 * | IEEE IEs(variable): Any received IEs comprising the |
1267 * | remaining portion of a received |
1268 * | association response frame. |
1269 * .------------------------------------------------------------.
1270 *
1271 * For simplistic handling, the status_code field can be used to determine
1272 * an association success (0) or failure (non-zero).
1273 *
1274 * @param pmpriv A pointer to mlan_private structure
1275 * @param resp A pointer to HostCmd_DS_COMMAND
1276 * @param pioctl_buf A pointer to mlan_ioctl_req structure
1277 *
1278 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1279 */
1280 mlan_status wlan_ret_802_11_associate(IN mlan_private *pmpriv, IN HostCmd_DS_COMMAND *resp, IN t_void *pioctl_buf)
1281 {
1282 mlan_status ret = MLAN_STATUS_SUCCESS;
1283 mlan_ioctl_req *pioctl_req = (mlan_ioctl_req *)pioctl_buf;
1284 IEEEtypes_AssocRsp_t *passoc_rsp;
1285 BSSDescriptor_t *pbss_desc;
1286 /* t_u8 enable_data = MTRUE; */
1287 /* t_u8 event_buf[100]; */
1288 /* mlan_event *pevent = (mlan_event *) event_buf; */
1289 t_u8 cur_mac[MLAN_MAC_ADDR_LENGTH] = {0x0};
1290 #if CONFIG_WMM
1291 t_u8 media_connected = pmpriv->media_connected;
1292 #endif
1293 /* mlan_adapter *pmadapter = pmpriv->adapter; */
1294
1295 #if CONFIG_HOST_MLME
1296 IEEEtypes_MgmtHdr_t *hdr;
1297 #endif
1298
1299 ENTER();
1300
1301 #if CONFIG_HOST_MLME
1302 if (pmpriv->curr_bss_params.host_mlme)
1303 {
1304 hdr = (IEEEtypes_MgmtHdr_t *)&resp->params;
1305 if (!__memcmp(pmpriv->adapter, hdr->BssId, pmpriv->pattempted_bss_desc->mac_address, MLAN_MAC_ADDR_LENGTH))
1306 {
1307 passoc_rsp = (IEEEtypes_AssocRsp_t *)((t_u8 *)(&resp->params) + sizeof(IEEEtypes_MgmtHdr_t));
1308 }
1309 else
1310 {
1311 passoc_rsp = (IEEEtypes_AssocRsp_t *)&resp->params;
1312 }
1313 }
1314 else
1315 #endif
1316
1317 passoc_rsp = (IEEEtypes_AssocRsp_t *)(void *)&resp->params;
1318 passoc_rsp->status_code = wlan_le16_to_cpu(passoc_rsp->status_code);
1319 if (pmpriv->media_connected == MTRUE)
1320 {
1321 (void)__memcpy(pmpriv->adapter, cur_mac, pmpriv->curr_bss_params.bss_descriptor.mac_address,
1322 MLAN_MAC_ADDR_LENGTH);
1323 }
1324
1325 /* fixme: This is not needed as of now. */
1326 if (passoc_rsp->status_code)
1327 {
1328 if (pmpriv->media_connected == MTRUE)
1329 {
1330 if (pmpriv->port_ctrl_mode == MTRUE)
1331 pmpriv->port_open = pmpriv->prior_port_status;
1332 if (!__memcmp(pmpriv->adapter, cur_mac, pmpriv->pattempted_bss_desc->mac_address, MLAN_MAC_ADDR_LENGTH))
1333 wlan_reset_connect_state(pmpriv, MTRUE);
1334 }
1335
1336 wifi_d(
1337 "ASSOC_RESP: Association Failed, "
1338 "status code = %d, a_id = 0x%x",
1339 wlan_le16_to_cpu(passoc_rsp->status_code), wlan_le16_to_cpu(passoc_rsp->a_id));
1340
1341 return MLAN_STATUS_FAILURE;
1342 }
1343
1344 /* Send a Media Connected event, according to the Spec */
1345 pmpriv->media_connected = MTRUE;
1346
1347 #if CONFIG_WMM_UAPSD
1348 pmpriv->adapter->pps_uapsd_mode = MFALSE;
1349 pmpriv->adapter->tx_lock_flag = MFALSE;
1350 #endif
1351
1352 /* Set the attempted BSSID Index to current */
1353 pbss_desc = pmpriv->pattempted_bss_desc;
1354
1355 PRINTM(MINFO, "ASSOC_RESP: %s\n", pbss_desc->ssid.ssid);
1356
1357 /* Make a copy of current BSSID descriptor */
1358 (void)__memcpy(pmpriv->adapter, &pmpriv->curr_bss_params.bss_descriptor, pbss_desc, sizeof(BSSDescriptor_t));
1359
1360 /* Update curr_bss_params */
1361 pmpriv->curr_bss_params.bss_descriptor.channel = pbss_desc->phy_param_set.ds_param_set.current_chan;
1362
1363 pmpriv->curr_bss_params.band = (t_u8)pbss_desc->bss_band;
1364
1365 if (pbss_desc->wmm_ie.vend_hdr.element_id == WMM_IE)
1366 {
1367 pmpriv->curr_bss_params.wmm_enabled = MTRUE;
1368 }
1369 else
1370 {
1371 pmpriv->curr_bss_params.wmm_enabled = MFALSE;
1372 }
1373
1374 if ((pmpriv->wmm_required ||
1375 ((pbss_desc->pht_cap != MNULL) && (pbss_desc->pht_cap->ieee_hdr.element_id == HT_CAPABILITY))) &&
1376 pmpriv->curr_bss_params.wmm_enabled)
1377 {
1378 pmpriv->wmm_enabled = MTRUE;
1379 }
1380 else
1381 {
1382 pmpriv->wmm_enabled = MFALSE;
1383 }
1384
1385 /* fixme: Enable if req */
1386 #if CONFIG_WMM_UAPSD
1387 pmpriv->curr_bss_params.wmm_uapsd_enabled = MFALSE;
1388
1389 if (pmpriv->wmm_enabled == MTRUE)
1390 {
1391 pmpriv->curr_bss_params.wmm_uapsd_enabled = pbss_desc->wmm_ie.qos_info.qos_uapsd;
1392 }
1393 #endif
1394 if (pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.wpa2_enabled)
1395 {
1396 pmpriv->wpa_is_gtk_set = MFALSE;
1397 }
1398
1399 /* Reset SNR/NF/RSSI values */
1400 pmpriv->data_rssi_last = 0;
1401 pmpriv->data_nf_last = 0;
1402 pmpriv->data_rssi_avg = 0;
1403 pmpriv->data_nf_avg = 0;
1404 pmpriv->bcn_rssi_last = 0;
1405 pmpriv->bcn_nf_last = 0;
1406 pmpriv->bcn_rssi_avg = 0;
1407 pmpriv->bcn_nf_avg = 0;
1408 pmpriv->rxpd_rate = 0;
1409 #ifdef SD8801
1410 pmpriv->rxpd_htinfo = 0;
1411 #else
1412 pmpriv->rxpd_rate_info = 0;
1413 #endif
1414 if (pbss_desc->pht_cap != MNULL)
1415 {
1416 if ((GETHT_MAXAMSDU(pbss_desc->pht_cap->ht_cap.ht_cap_info)) != 0U)
1417 {
1418 pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_8K;
1419 }
1420 else
1421 {
1422 pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_4K;
1423 }
1424 }
1425
1426 #if CONFIG_WMM
1427 /* Add the ra_list here for infra mode as there will be only 1 ra always */
1428 if (media_connected == MTRUE)
1429 {
1430 if (0 == wlan_ralist_update_enh(pmpriv, cur_mac, pmpriv->curr_bss_params.bss_descriptor.mac_address))
1431 {
1432 wlan_ralist_add_enh(pmpriv, pmpriv->curr_bss_params.bss_descriptor.mac_address);
1433 }
1434
1435 wlan_11n_cleanup_reorder_tbl(pmpriv);
1436 wlan_11n_deleteall_txbastream_tbl(pmpriv);
1437 }
1438 else
1439 {
1440 wlan_ralist_add_enh(pmpriv, pmpriv->curr_bss_params.bss_descriptor.mac_address);
1441 }
1442 #endif
1443
1444 if (!pmpriv->sec_info.wpa_enabled && !pmpriv->sec_info.wpa2_enabled && !pmpriv->sec_info.ewpa_enabled &&
1445 !pmpriv->sec_info.wapi_enabled)
1446 {
1447 /* We are in Open/WEP mode, open port immediately */
1448 if (pmpriv->port_ctrl_mode == MTRUE)
1449 {
1450 pmpriv->port_open = MTRUE;
1451 PRINTM(MINFO, "ASSOC_RESP: port_status = OPEN\n");
1452 }
1453 }
1454
1455 if (pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.wpa2_enabled || pmpriv->sec_info.ewpa_enabled ||
1456 pmpriv->sec_info.wapi_enabled)
1457 {
1458 pmpriv->scan_block = MTRUE;
1459 }
1460
1461 /* done: */
1462 /* Need to indicate IOCTL complete */
1463 if (pioctl_req != MNULL)
1464 {
1465 pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
1466 }
1467
1468 LEAVE();
1469 return ret;
1470 }
1471
1472 /**
1473 * @brief Associated to a specific BSS discovered in a scan
1474 *
1475 * @param pmpriv A pointer to mlan_private structure
1476 * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
1477 * @param pbss_desc A pointer to the BSS descriptor to associate with.
1478 *
1479 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1480 */
1481 mlan_status wlan_associate(IN mlan_private *pmpriv, IN t_void *pioctl_buf, IN BSSDescriptor_t *pbss_desc)
1482 {
1483 mlan_status ret = MLAN_STATUS_SUCCESS;
1484 t_u8 current_bssid[MLAN_MAC_ADDR_LENGTH] = {0x0};
1485 pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
1486
1487 ENTER();
1488
1489 /* Return error if the pmadapter or table entry is not marked as infra */
1490 if ((pmpriv->bss_mode != MLAN_BSS_MODE_INFRA) || (pbss_desc->bss_mode != MLAN_BSS_MODE_INFRA))
1491 {
1492 if (pioctl_req != MNULL)
1493 {
1494 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
1495 }
1496 LEAVE();
1497 return MLAN_STATUS_FAILURE;
1498 }
1499
1500 (void)__memcpy(pmpriv->adapter, ¤t_bssid, &pmpriv->curr_bss_params.bss_descriptor.mac_address,
1501 sizeof(current_bssid));
1502
1503 /* Clear any past association response stored for application retrieval */
1504 /* fixme: enable this later if assoc rsp buffer is needed */
1505 /* pmpriv->assoc_rsp_size = 0; */
1506
1507 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_ASSOCIATE, HostCmd_ACT_GEN_SET, 0, pioctl_buf, pbss_desc);
1508
1509 LEAVE();
1510 return ret;
1511 }
1512
1513 /**
1514 * @brief Convert band to radio type used in channel TLV
1515 *
1516 * @param band Band enumeration to convert to a channel TLV radio type
1517 *
1518 * @return Radio type designator for use in a channel TLV
1519 */
1520 t_u8 wlan_band_to_radio_type(IN t_u8 band)
1521 {
1522 t_u8 ret_radio_type;
1523
1524 ENTER();
1525
1526 switch (band)
1527 {
1528 case BAND_A:
1529 case BAND_AN:
1530 case BAND_A | BAND_AN:
1531 ret_radio_type = HostCmd_SCAN_RADIO_TYPE_A;
1532 break;
1533 case BAND_B:
1534 case BAND_G:
1535 case BAND_B | BAND_G:
1536 default:
1537 ret_radio_type = HostCmd_SCAN_RADIO_TYPE_BG;
1538 break;
1539 }
1540
1541 LEAVE();
1542 return ret_radio_type;
1543 }
1544
1545 bool wlan_use_non_default_ht_vht_cap(IN BSSDescriptor_t *pbss_desc)
1546 {
1547 /* If connect to 11ax or non-brcm AP, still use default HT/VHT cap */
1548 if (
1549 #if CONFIG_11AX
1550 pbss_desc->phe_cap ||
1551 #endif
1552 (!pbss_desc->brcm_ie_exist && !pbss_desc->epigram_ie_exist))
1553 return false;
1554
1555 /* In HT cap, check if "Transmit Null Data Packet" is set to 0,
1556 * In VHT cap, check if "Number of Sounding Dimensions" is set to 3,
1557 * If both are true, do not use default HT/VHT cap */
1558 if ((pbss_desc->pht_cap && (((pbss_desc->ht_cap_saved.ht_cap.tx_bf_cap >> 4) & 0x1) == 0x0))
1559 #if CONFIG_11AC
1560 && (!pbss_desc->pvht_cap ||
1561 (pbss_desc->pvht_cap && (GET_VHTCAP_NUMSNDDM(pbss_desc->vht_cap_saved.vht_cap.vht_cap_info) == 0x2)))
1562 #endif
1563 )
1564 {
1565 return true;
1566 }
1567
1568 return false;
1569 }
1570