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, &current_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