1 /** @file mlan_join.c
2 *
3 * @brief Functions implementing wlan infrastructure and adhoc join routines
4 *
5 * IOCTL handlers as well as command preparation and response routines
6 * for sending adhoc start, adhoc join, and association commands
7 * to the firmware.
8 *
9 *
10 * Copyright 2008-2022 NXP
11 *
12 * This software file (the File) is distributed by NXP
13 * under the terms of the GNU General Public License Version 2, June 1991
14 * (the License). You may use, redistribute and/or modify the File in
15 * accordance with the terms and conditions of the License, a copy of which
16 * is available by writing to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
18 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
19 *
20 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
22 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
23 * this warranty disclaimer.
24 *
25 */
26
27 /******************************************************
28 Change log:
29 10/30/2008: initial version
30 ******************************************************/
31
32 #include "mlan.h"
33 #include "mlan_join.h"
34 #include "mlan_util.h"
35 #include "mlan_fw.h"
36 #include "mlan_main.h"
37 #include "mlan_wmm.h"
38 #include "mlan_11n.h"
39 #include "mlan_11ac.h"
40 #include "mlan_11ax.h"
41 #include "mlan_11h.h"
42 #ifdef DRV_EMBEDDED_SUPPLICANT
43 #include "authenticator_api.h"
44 #endif
45 /********************************************************
46 Local Constants
47 ********************************************************/
48
49 /********************************************************
50 Local Variables
51 ********************************************************/
52
53 /********************************************************
54 Global Variables
55 ********************************************************/
56
57 /********************************************************
58 Local Functions
59 ********************************************************/
60 /**
61 * @brief Append a generic IE as a pass through TLV to a TLV buffer.
62 *
63 * This function is called from the network join command prep. routine.
64 * If the IE buffer has been setup by the application, this routine appends
65 * the buffer as a pass through TLV type to the request.
66 *
67 * @param priv A pointer to mlan_private structure
68 * @param ppbuffer pointer to command buffer pointer
69 *
70 * @return bytes added to the buffer
71 */
wlan_cmd_append_generic_ie(mlan_private * priv,t_u8 ** ppbuffer)72 static int wlan_cmd_append_generic_ie(mlan_private *priv, t_u8 **ppbuffer)
73 {
74 int ret_len = 0;
75 MrvlIEtypesHeader_t ie_header;
76
77 ENTER();
78
79 /* Null Checks */
80 if (ppbuffer == MNULL) {
81 LEAVE();
82 return 0;
83 }
84 if (*ppbuffer == MNULL) {
85 LEAVE();
86 return 0;
87 }
88
89 /*
90 * If there is a generic ie buffer setup, append it to the return
91 * parameter buffer pointer.
92 */
93 if (priv->gen_ie_buf_len) {
94 PRINTM(MINFO, "append generic IE %d to %p\n",
95 priv->gen_ie_buf_len, *ppbuffer);
96
97 /* Wrap the generic IE buffer with a pass through TLV type */
98 ie_header.type = wlan_cpu_to_le16(TLV_TYPE_PASSTHROUGH);
99 ie_header.len = wlan_cpu_to_le16(priv->gen_ie_buf_len);
100 memcpy_ext(priv->adapter, *ppbuffer, &ie_header,
101 sizeof(ie_header), sizeof(ie_header));
102
103 /* Increment the return size and the return buffer pointer param
104 */
105 *ppbuffer += sizeof(ie_header);
106 ret_len += sizeof(ie_header);
107
108 /* Copy the generic IE buffer to the output buffer, advance
109 * pointer */
110 memcpy_ext(priv->adapter, *ppbuffer, priv->gen_ie_buf,
111 priv->gen_ie_buf_len, priv->gen_ie_buf_len);
112
113 /* Increment the return size and the return buffer pointer param
114 */
115 *ppbuffer += priv->gen_ie_buf_len;
116 ret_len += priv->gen_ie_buf_len;
117
118 /* Reset the generic IE buffer */
119 priv->gen_ie_buf_len = 0;
120 }
121
122 /* return the length appended to the buffer */
123 LEAVE();
124 return ret_len;
125 }
126
127 /**
128 * @brief Append IE as a pass through TLV to a TLV buffer.
129 *
130 * This routine appends IE as a pass through TLV type to the request.
131 *
132 * @param priv A pointer to mlan_private structure
133 * @param ie A pointer to IE buffer
134 * @param ppbuffer pointer to command buffer pointer
135 *
136 * @return bytes added to the buffer
137 */
wlan_cmd_append_pass_through_ie(mlan_private * priv,IEEEtypes_Generic_t * ie,t_u8 ** ppbuffer)138 static int wlan_cmd_append_pass_through_ie(mlan_private *priv,
139 IEEEtypes_Generic_t *ie,
140 t_u8 **ppbuffer)
141 {
142 int ret_len = 0;
143 MrvlIEtypesHeader_t ie_header;
144
145 ENTER();
146
147 /* Null Checks */
148 if (ppbuffer == MNULL) {
149 LEAVE();
150 return 0;
151 }
152 if (*ppbuffer == MNULL) {
153 LEAVE();
154 return 0;
155 }
156 if (ie->ieee_hdr.len) {
157 PRINTM(MINFO, "append generic IE %d to %p\n", ie->ieee_hdr.len,
158 *ppbuffer);
159
160 /* Wrap the generic IE buffer with a pass through TLV type */
161 ie_header.type = wlan_cpu_to_le16(TLV_TYPE_PASSTHROUGH);
162 ie_header.len = wlan_cpu_to_le16(ie->ieee_hdr.len +
163 sizeof(IEEEtypes_Header_t));
164 memcpy_ext(priv->adapter, *ppbuffer, &ie_header,
165 sizeof(ie_header), sizeof(ie_header));
166
167 /* Increment the return size and the return buffer pointer param
168 */
169 *ppbuffer += sizeof(ie_header);
170 ret_len += sizeof(ie_header);
171
172 /* Copy the generic IE buffer to the output buffer, advance
173 * pointer */
174 memcpy_ext(priv->adapter, *ppbuffer, ie,
175 ie->ieee_hdr.len + sizeof(IEEEtypes_Header_t),
176 ie->ieee_hdr.len + sizeof(IEEEtypes_Header_t));
177
178 /* Increment the return size and the return buffer pointer param
179 */
180 *ppbuffer += ie->ieee_hdr.len + sizeof(IEEEtypes_Header_t);
181 ret_len += ie->ieee_hdr.len + sizeof(IEEEtypes_Header_t);
182 }
183 /* return the length appended to the buffer */
184 LEAVE();
185 return ret_len;
186 }
187
188 /**
189 * @brief Append TSF tracking info from the scan table for the target AP
190 *
191 * This function is called from the network join command prep. routine.
192 * The TSF table TSF sent to the firmware contains two TSF values:
193 * - the TSF of the target AP from its previous beacon/probe response
194 * - the TSF timestamp of our local MAC at the time we observed the
195 * beacon/probe response.
196 *
197 * The firmware uses the timestamp values to set an initial TSF value
198 * in the MAC for the new association after a reassociation attempt.
199 *
200 * @param pmpriv A pointer to mlan_private structure
201 * @param ppbuffer A pointer to command buffer pointer
202 * @param pbss_desc A pointer to the BSS Descriptor from the scan table of
203 * the AP we are trying to join
204 *
205 * @return bytes added to the buffer
206 */
wlan_cmd_append_tsf_tlv(mlan_private * pmriv,t_u8 ** ppbuffer,BSSDescriptor_t * pbss_desc)207 static int wlan_cmd_append_tsf_tlv(mlan_private *pmriv, t_u8 **ppbuffer,
208 BSSDescriptor_t *pbss_desc)
209 {
210 MrvlIEtypes_TsfTimestamp_t tsf_tlv;
211 t_u64 tsf_val;
212
213 ENTER();
214
215 /* Null Checks */
216 if (ppbuffer == MNULL) {
217 LEAVE();
218 return 0;
219 }
220 if (*ppbuffer == MNULL) {
221 LEAVE();
222 return 0;
223 }
224
225 memset(pmriv->adapter, &tsf_tlv, 0x00,
226 sizeof(MrvlIEtypes_TsfTimestamp_t));
227
228 tsf_tlv.header.type = wlan_cpu_to_le16(TLV_TYPE_TSFTIMESTAMP);
229 tsf_tlv.header.len = wlan_cpu_to_le16(2 * sizeof(tsf_val));
230
231 memcpy_ext(pmriv->adapter, *ppbuffer, &tsf_tlv, sizeof(tsf_tlv.header),
232 sizeof(tsf_tlv.header));
233 *ppbuffer += sizeof(tsf_tlv.header);
234
235 /* TSF timestamp from the firmware TSF when the bcn/prb rsp was received
236 */
237 tsf_val = wlan_cpu_to_le64(pbss_desc->network_tsf);
238 memcpy_ext(pmriv->adapter, *ppbuffer, &tsf_val, sizeof(tsf_val),
239 sizeof(tsf_val));
240 *ppbuffer += sizeof(tsf_val);
241
242 memcpy_ext(pmriv->adapter, &tsf_val, pbss_desc->time_stamp,
243 sizeof(pbss_desc->time_stamp), sizeof(tsf_val));
244
245 PRINTM(MINFO, "ASSOC: TSF offset calc: %016llx - %016llx\n", tsf_val,
246 pbss_desc->network_tsf);
247
248 memcpy_ext(pmriv->adapter, *ppbuffer, &tsf_val, sizeof(tsf_val),
249 sizeof(tsf_val));
250 *ppbuffer += sizeof(tsf_val);
251
252 LEAVE();
253 return sizeof(tsf_tlv.header) + (2 * sizeof(tsf_val));
254 }
255
256 /**
257 * @brief This function finds out the common rates between rate1 and rate2.
258 *
259 * It will fill common rates in rate1 as output if found.
260 *
261 * NOTE: Setting the MSB of the basic rates needs to be taken
262 * care of, either before or after calling this function
263 *
264 * @param pmpriv A pointer to mlan_private structure
265 * @param rate1 the buffer which keeps input and output
266 * @param rate1_size the size of rate1 buffer
267 * @param rate2 the buffer which keeps rate2
268 * @param rate2_size the size of rate2 buffer.
269 *
270 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
271 */
wlan_get_common_rates(mlan_private * pmpriv,t_u8 * rate1,t_u32 rate1_size,t_u8 * rate2,t_u32 rate2_size)272 static mlan_status wlan_get_common_rates(mlan_private *pmpriv, t_u8 *rate1,
273 t_u32 rate1_size, t_u8 *rate2,
274 t_u32 rate2_size)
275 {
276 mlan_status ret = MLAN_STATUS_SUCCESS;
277 mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
278 t_u8 *ptr = rate1;
279 t_u8 *tmp = MNULL;
280 t_u32 i, j;
281
282 ENTER();
283
284 ret = pcb->moal_malloc(pmpriv->adapter->pmoal_handle, rate1_size,
285 MLAN_MEM_DEF | MLAN_MEM_FLAG_ATOMIC, &tmp);
286 if (ret != MLAN_STATUS_SUCCESS || !tmp) {
287 PRINTM(MERROR, "Failed to allocate buffer\n");
288 ret = MLAN_STATUS_FAILURE;
289 goto done;
290 }
291
292 memcpy_ext(pmpriv->adapter, tmp, rate1, rate1_size, rate1_size);
293 memset(pmpriv->adapter, rate1, 0, rate1_size);
294
295 for (i = 0; rate2[i] && i < rate2_size; i++) {
296 for (j = 0; tmp[j] && j < rate1_size; j++) {
297 /* Check common rate, excluding the bit
298 * for basic rate */
299 if ((rate2[i] & 0x7F) == (tmp[j] & 0x7F)) {
300 *rate1++ = tmp[j];
301 break;
302 }
303 }
304 }
305
306 HEXDUMP("rate1 (AP) Rates", tmp, rate1_size);
307 HEXDUMP("rate2 (Card) Rates", rate2, rate2_size);
308 HEXDUMP("Common Rates", ptr, rate1 - ptr);
309 PRINTM(MINFO, "Tx DataRate is set to 0x%X\n", pmpriv->data_rate);
310
311 if (!pmpriv->is_data_rate_auto) {
312 while (*ptr) {
313 if ((*ptr & 0x7f) == pmpriv->data_rate) {
314 ret = MLAN_STATUS_SUCCESS;
315 goto done;
316 }
317 ptr++;
318 }
319 PRINTM(MMSG,
320 "Previously set fixed data rate %#x is not "
321 "compatible with the network\n",
322 pmpriv->data_rate);
323
324 ret = MLAN_STATUS_FAILURE;
325 goto done;
326 }
327
328 ret = MLAN_STATUS_SUCCESS;
329 done:
330 if (tmp)
331 pcb->moal_mfree(pmpriv->adapter->pmoal_handle, tmp);
332
333 LEAVE();
334 return ret;
335 }
336
337 /**
338 * @brief Create the intersection of the rates supported by a target BSS and
339 * our pmadapter settings for use in an assoc/join command.
340 *
341 * @param pmpriv A pointer to mlan_private structure
342 * @param pbss_desc BSS Descriptor whose rates are used in the setup
343 * @param pout_rates Output: Octet array of rates common between the BSS
344 * and the pmadapter supported rates settings
345 * @param pout_rates_size Output: Number of rates/octets set in pout_rates
346 *
347 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
348 */
wlan_setup_rates_from_bssdesc(mlan_private * pmpriv,BSSDescriptor_t * pbss_desc,t_u8 * pout_rates,t_u32 * pout_rates_size)349 static mlan_status wlan_setup_rates_from_bssdesc(mlan_private *pmpriv,
350 BSSDescriptor_t *pbss_desc,
351 t_u8 *pout_rates,
352 t_u32 *pout_rates_size)
353 {
354 t_u8 card_rates[WLAN_SUPPORTED_RATES];
355 t_u32 card_rates_size = 0;
356 ENTER();
357 /* Copy AP supported rates */
358 memcpy_ext(pmpriv->adapter, pout_rates, pbss_desc->supported_rates,
359 WLAN_SUPPORTED_RATES, WLAN_SUPPORTED_RATES);
360
361 if ((pmpriv->adapter->region_code == COUNTRY_CODE_JP_40 ||
362 pmpriv->adapter->region_code == COUNTRY_CODE_JP_FF) &&
363 (pbss_desc->phy_param_set.ds_param_set.current_chan == 14)) {
364 /* Special Case: For Japan, 11G rates on CH14 are not allowed*/
365 card_rates_size = wlan_get_supported_rates(
366 pmpriv, pmpriv->bss_mode, BAND_B, card_rates);
367 } else {
368 /* Get the STA supported rates */
369 card_rates_size =
370 wlan_get_supported_rates(pmpriv, pmpriv->bss_mode,
371 pmpriv->config_bands,
372 card_rates);
373 }
374 /* Get the common rates between AP and STA supported rates */
375 if (wlan_get_common_rates(pmpriv, pout_rates, WLAN_SUPPORTED_RATES,
376 card_rates, card_rates_size)) {
377 *pout_rates_size = 0;
378 PRINTM(MERROR, "wlan_get_common_rates failed\n");
379 LEAVE();
380 return MLAN_STATUS_FAILURE;
381 }
382
383 *pout_rates_size =
384 MIN(wlan_strlen((char *)pout_rates), WLAN_SUPPORTED_RATES);
385
386 LEAVE();
387 return MLAN_STATUS_SUCCESS;
388 }
389
390 /**
391 * @brief Update the scan entry TSF timestamps to reflect a new association
392 *
393 * @param pmpriv A pointer to mlan_private structure
394 * @param pnew_bss_desc A pointer to the newly associated AP's scan table entry
395 *
396 * @return N/A
397 */
wlan_update_tsf_timestamps(mlan_private * pmpriv,BSSDescriptor_t * pnew_bss_desc)398 static t_void wlan_update_tsf_timestamps(mlan_private *pmpriv,
399 BSSDescriptor_t *pnew_bss_desc)
400 {
401 mlan_adapter *pmadapter = pmpriv->adapter;
402 t_u32 table_idx;
403 t_u64 new_tsf_base;
404 t_s64 tsf_delta;
405
406 ENTER();
407
408 memcpy_ext(pmpriv->adapter, &new_tsf_base, pnew_bss_desc->time_stamp,
409 sizeof(pnew_bss_desc->time_stamp), sizeof(new_tsf_base));
410
411 tsf_delta = new_tsf_base - pnew_bss_desc->network_tsf;
412
413 PRINTM(MINFO, "TSF: Update TSF timestamps, 0x%016llx -> 0x%016llx\n",
414 pnew_bss_desc->network_tsf, new_tsf_base);
415
416 for (table_idx = 0; table_idx < pmadapter->num_in_scan_table;
417 table_idx++) {
418 pmadapter->pscan_table[table_idx].network_tsf += tsf_delta;
419 }
420
421 LEAVE();
422 }
423
424 /**
425 * @brief Append a wapi IE
426 *
427 * This function is called from the network join command prep. routine.
428 * If the IE buffer has been setup by the application, this routine appends
429 * the buffer as a wapi TLV type to the request.
430 *
431 * @param priv A pointer to mlan_private structure
432 * @param ppbuffer pointer to command buffer pointer
433 *
434 * @return bytes added to the buffer
435 */
wlan_cmd_append_wapi_ie(mlan_private * priv,t_u8 ** ppbuffer)436 static int wlan_cmd_append_wapi_ie(mlan_private *priv, t_u8 **ppbuffer)
437 {
438 int retlen = 0;
439 MrvlIEtypesHeader_t ie_header;
440
441 ENTER();
442
443 /* Null Checks */
444 if (ppbuffer == MNULL) {
445 LEAVE();
446 return 0;
447 }
448 if (*ppbuffer == MNULL) {
449 LEAVE();
450 return 0;
451 }
452
453 /*
454 * If there is a wapi ie buffer setup, append it to the return
455 * parameter buffer pointer.
456 */
457 if (priv->wapi_ie_len) {
458 PRINTM(MCMND, "append wapi ie %d to %p\n", priv->wapi_ie_len,
459 *ppbuffer);
460
461 /* Wrap the generic IE buffer with a pass through TLV type */
462 ie_header.type = wlan_cpu_to_le16(TLV_TYPE_WAPI_IE);
463 ie_header.len = wlan_cpu_to_le16(priv->wapi_ie_len);
464 memcpy_ext(priv->adapter, *ppbuffer, &ie_header,
465 sizeof(ie_header), sizeof(ie_header));
466
467 /* Increment the return size and the return buffer pointer param
468 */
469 *ppbuffer += sizeof(ie_header);
470 retlen += sizeof(ie_header);
471
472 /* Copy the wapi IE buffer to the output buffer, advance pointer
473 */
474 memcpy_ext(priv->adapter, *ppbuffer, priv->wapi_ie,
475 priv->wapi_ie_len, priv->wapi_ie_len);
476
477 /* Increment the return size and the return buffer pointer param
478 */
479 *ppbuffer += priv->wapi_ie_len;
480 retlen += priv->wapi_ie_len;
481 }
482 /* return the length appended to the buffer */
483 LEAVE();
484 return retlen;
485 }
486
487 /**
488 * @brief Append a osen IE
489 *
490 * This function is called from the network join command prep. routine.
491 * If the IE buffer has been setup by the application, this routine appends
492 * the buffer as a osen TLV type to the request.
493 *
494 * @param priv A pointer to mlan_private structure
495 * @param ppbuffer pointer to command buffer pointer
496 *
497 * @return bytes added to the buffer
498 */
wlan_cmd_append_osen_ie(mlan_private * priv,t_u8 ** ppbuffer)499 static int wlan_cmd_append_osen_ie(mlan_private *priv, t_u8 **ppbuffer)
500 {
501 int retlen = 0;
502 MrvlIEtypesHeader_t ie_header;
503
504 ENTER();
505
506 /* Null Checks */
507 if (ppbuffer == MNULL) {
508 LEAVE();
509 return 0;
510 }
511 if (*ppbuffer == MNULL) {
512 LEAVE();
513 return 0;
514 }
515
516 /*
517 * If there is a osen ie buffer setup, append it to the return
518 * parameter buffer pointer.
519 */
520 if (priv->osen_ie_len) {
521 PRINTM(MCMND, "append osen ie %d to %p\n", priv->osen_ie_len,
522 *ppbuffer);
523
524 /* Wrap the generic IE buffer with a pass through TLV type */
525 ie_header.type = wlan_cpu_to_le16(TLV_TYPE_VENDOR_SPECIFIC_IE);
526 ie_header.len = wlan_cpu_to_le16(priv->osen_ie[1]);
527 memcpy_ext(priv->adapter, *ppbuffer, &ie_header,
528 sizeof(ie_header), sizeof(ie_header));
529
530 /* Increment the return size and the return buffer pointer param
531 */
532 *ppbuffer += sizeof(ie_header);
533 retlen += sizeof(ie_header);
534
535 /* Copy the osen IE buffer to the output buffer, advance pointer
536 */
537 memcpy_ext(priv->adapter, *ppbuffer, &priv->osen_ie[2],
538 priv->osen_ie[1], priv->osen_ie[1]);
539
540 /* Increment the return size and the return buffer pointer param
541 */
542 *ppbuffer += priv->osen_ie[1];
543 retlen += priv->osen_ie[1];
544 }
545 /* return the length appended to the buffer */
546 LEAVE();
547 return retlen;
548 }
549
550 /**
551 * @brief This function get the rsn_cap from RSN ie buffer.
552 *
553 * @param pmpriv A pointer to mlan_private structure
554 *
555 * @param data A pointer to rsn_ie data after IE header
556 * @param return rsn_cap
557 */
wlan_get_rsn_cap(t_u8 * data)558 static t_u16 wlan_get_rsn_cap(t_u8 *data)
559 {
560 t_u16 rsn_cap = 0;
561 t_u16 *ptr;
562 t_u16 pairwise_cipher_count = 0;
563 t_u16 akm_suite_count = 0;
564 /* rsn_cap = data + 2 bytes version + 4 bytes
565 * group_cipher_suite + 2 bytes pairwise_cipher_count +
566 * pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN + 2 bytes
567 * akm_suite_count + akm_suite_count * AKM_SUITE_LEN
568 */
569 ptr = (t_u16 *)(data + sizeof(t_u16) + 4 * sizeof(t_u8));
570 pairwise_cipher_count = wlan_le16_to_cpu(*ptr);
571 ptr = (t_u16 *)(data + sizeof(t_u16) + 4 * sizeof(t_u8) +
572 sizeof(t_u16) +
573 pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN);
574 akm_suite_count = wlan_le16_to_cpu(*ptr);
575 ptr = (t_u16 *)(data + sizeof(t_u16) + 4 * sizeof(t_u8) +
576 sizeof(t_u16) +
577 pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN +
578 sizeof(t_u16) + akm_suite_count * AKM_SUITE_LEN);
579 rsn_cap = wlan_le16_to_cpu(*ptr);
580 PRINTM(MCMND, "rsn_cap=0x%x\n", rsn_cap);
581 return rsn_cap;
582 }
583
584 /**
585 * @brief This function check if we should enable 11w
586 *
587 * @param pmpriv A pointer to mlan_private structure
588 *
589 * @param BSSDescriptor_t A pointer to BSSDescriptor_t data structure
590 * @param return MTRUE/MFALSE
591 */
wlan_use_mfp(mlan_private * pmpriv,BSSDescriptor_t * pbss_desc)592 static t_u8 wlan_use_mfp(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc)
593 {
594 t_u16 ap_rsn_cap = 0;
595 t_u16 sta_rsn_cap = 0;
596 t_u8 ap_mfpc, ap_mfpr;
597 t_u8 sta_mfpc, sta_mfpr;
598
599 if (pmpriv->wpa_ie[0] != RSN_IE)
600 return 0;
601 sta_rsn_cap = wlan_get_rsn_cap(pmpriv->wpa_ie + 2);
602 if (!pbss_desc->prsn_ie)
603 return 0;
604 ap_rsn_cap = wlan_get_rsn_cap(pbss_desc->prsn_ie->data);
605 ap_mfpc = ((ap_rsn_cap & (0x1 << MFPC_BIT)) == (0x1 << MFPC_BIT));
606 ap_mfpr = ((ap_rsn_cap & (0x1 << MFPR_BIT)) == (0x1 << MFPR_BIT));
607 sta_mfpc = ((sta_rsn_cap & (0x1 << MFPC_BIT)) == (0x1 << MFPC_BIT));
608 sta_mfpr = ((sta_rsn_cap & (0x1 << MFPR_BIT)) == (0x1 << MFPR_BIT));
609 if (!ap_mfpc && !ap_mfpr)
610 return MFALSE;
611 if (!sta_mfpc && !sta_mfpr)
612 return MFALSE;
613 return MTRUE;
614 }
615
616 /********************************************************
617 Global Functions
618 ********************************************************/
619
620 /**
621 * @brief This function updates RSN IE in the association request.
622 *
623 * @param pmpriv A pointer to mlan_private structure
624 *
625 * @param ptlv_rsn_ie A pointer to rsn_ie TLV
626 */
wlan_update_rsn_ie(mlan_private * pmpriv,MrvlIEtypes_RsnParamSet_t * ptlv_rsn_ie)627 static int wlan_update_rsn_ie(mlan_private *pmpriv,
628 MrvlIEtypes_RsnParamSet_t *ptlv_rsn_ie)
629 {
630 t_u16 *prsn_cap;
631 t_u16 *ptr;
632 t_u16 *akm_suite_count_ptr;
633 t_u16 pmf_mask = 0x00;
634 t_u8 *temp;
635 t_u16 pairwise_cipher_count = 0;
636 t_u16 akm_suite_count = 0;
637 t_u16 temp_akm_suite_count = 0;
638 int found = 0;
639 t_u8 sha_256_oui[4] = {0x00, 0x0f, 0xac, 0x06};
640 t_u8 sae_oui[4] = {0x00, 0x0f, 0xac, 0x08};
641 mlan_adapter *pmadapter = pmpriv->adapter;
642
643 int ap_mfpc = 0, ap_mfpr = 0, ret = MLAN_STATUS_SUCCESS;
644
645 pmf_mask = (((pmpriv->pmfcfg.mfpc << MFPC_BIT) |
646 (pmpriv->pmfcfg.mfpr << MFPR_BIT)) |
647 (~PMF_MASK));
648 /* prsn_cap = prsn_ie->rsn_ie + 2 bytes version + 4 bytes
649 * group_cipher_suite + 2 bytes pairwise_cipher_count +
650 * pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN + 2 bytes
651 * akm_suite_count + akm_suite_count * AKM_SUITE_LEN
652 */
653 ptr = (t_u16 *)(ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8));
654 pairwise_cipher_count = wlan_le16_to_cpu(*ptr);
655 ptr = (t_u16 *)(ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8) +
656 sizeof(t_u16) +
657 pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN);
658 temp_akm_suite_count = wlan_le16_to_cpu(*ptr);
659 akm_suite_count = wlan_le16_to_cpu(*ptr);
660 /* Save pointer to akm_suite_count in RSN IE to update it later */
661 akm_suite_count_ptr = ptr;
662 temp = ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8) +
663 sizeof(t_u16) +
664 pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN +
665 sizeof(t_u16);
666 /* ptr now points to the 1st AKM suite */
667 if (temp_akm_suite_count > 1) {
668 while (temp_akm_suite_count) {
669 if (pmpriv->sec_info.authentication_mode ==
670 MLAN_AUTH_MODE_SAE) {
671 if (!memcmp(pmadapter, temp, sae_oui,
672 AKM_SUITE_LEN)) {
673 found = 1;
674 break;
675 }
676 } else if (!memcmp(pmadapter, temp, sha_256_oui,
677 AKM_SUITE_LEN)) {
678 found = 1;
679 break;
680 }
681 temp += AKM_SUITE_LEN;
682 temp_akm_suite_count--;
683 }
684 if (found) {
685 /* Copy SHA256 as AKM suite */
686 memcpy_ext(pmadapter,
687 ptlv_rsn_ie->rsn_ie +
688 (sizeof(t_u16) + 4 * sizeof(t_u8) +
689 sizeof(t_u16) +
690 pairwise_cipher_count *
691 PAIRWISE_CIPHER_SUITE_LEN +
692 sizeof(t_u16)),
693 temp, AKM_SUITE_LEN, AKM_SUITE_LEN);
694 /* Shift remaining bytes of RSN IE after this */
695 memmove(pmadapter,
696 ptlv_rsn_ie->rsn_ie +
697 (sizeof(t_u16) + 4 * sizeof(t_u8) +
698 sizeof(t_u16) +
699 pairwise_cipher_count *
700 PAIRWISE_CIPHER_SUITE_LEN +
701 sizeof(t_u16) + AKM_SUITE_LEN),
702 ptlv_rsn_ie->rsn_ie +
703 (sizeof(t_u16) + 4 * sizeof(t_u8) +
704 sizeof(t_u16) +
705 pairwise_cipher_count *
706 PAIRWISE_CIPHER_SUITE_LEN +
707 sizeof(t_u16) +
708 akm_suite_count * AKM_SUITE_LEN),
709 ptlv_rsn_ie->header.len -
710 (sizeof(t_u16) + 4 * sizeof(t_u8) +
711 sizeof(t_u16) +
712 pairwise_cipher_count *
713 PAIRWISE_CIPHER_SUITE_LEN +
714 sizeof(t_u16) +
715 akm_suite_count * AKM_SUITE_LEN));
716 ptlv_rsn_ie->header.len =
717 ptlv_rsn_ie->header.len -
718 (akm_suite_count - 1) * AKM_SUITE_LEN;
719 /* Update akm suite count */
720 akm_suite_count = 1;
721 *akm_suite_count_ptr = akm_suite_count;
722 }
723 }
724 ptr = (t_u16 *)(ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8) +
725 sizeof(t_u16) +
726 pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN +
727 sizeof(t_u16) + akm_suite_count * AKM_SUITE_LEN);
728 prsn_cap = ptr;
729
730 ap_mfpc = ((*prsn_cap & (0x1 << MFPC_BIT)) == (0x1 << MFPC_BIT));
731 ap_mfpr = ((*prsn_cap & (0x1 << MFPR_BIT)) == (0x1 << MFPR_BIT));
732
733 if ((!ap_mfpc && !ap_mfpr && pmpriv->pmfcfg.mfpr) ||
734 ((!ap_mfpc) && ap_mfpr) ||
735 (ap_mfpc && ap_mfpr && (!pmpriv->pmfcfg.mfpc))) {
736 PRINTM(MERROR,
737 "Mismatch in PMF config of STA and AP, can't associate to AP\n");
738 return MLAN_STATUS_FAILURE;
739 }
740 if ((pmpriv->pmfcfg.mfpr && pmpriv->pmfcfg.mfpc) ||
741 pmpriv->pmfcfg.mfpc) {
742 *prsn_cap |= PMF_MASK;
743 *prsn_cap &= pmf_mask;
744 }
745
746 return ret;
747 }
748
749 /**
750 * @brief This function is to find FT AKM in RSN.
751 *
752 * @param pmpriv A pointer to mlan_private structure
753 *
754 * @param rsn_ie A pointer to rsn_ie
755 *
756 */
wlan_ft_akm_is_used(mlan_private * pmpriv,t_u8 * rsn_ie)757 t_u8 wlan_ft_akm_is_used(mlan_private *pmpriv, t_u8 *rsn_ie)
758 {
759 t_u8 *temp;
760 t_u16 count;
761 t_u16 pairwise_cipher_count = 0;
762 t_u16 akm_suite_count = 0;
763 t_u8 found = 0;
764 t_u8 rsn_ft_1x_oui[4] = {0x00, 0x0f, 0xac, 0x03};
765 t_u8 rsn_ft_psk_oui[4] = {0x00, 0x0f, 0xac, 0x04};
766 t_u8 rsn_ft_sae_oui[4] = {0x00, 0x0f, 0xac, 0x09};
767 mlan_adapter *pmadapter = pmpriv->adapter;
768
769 ENTER();
770
771 if (!rsn_ie)
772 goto done;
773
774 if (rsn_ie[0] != RSN_IE)
775 goto done;
776
777 /* 2 bytes header + 2 bytes version + 4 bytes group_cipher_suite +
778 * 2 bytes pairwise_cipher_count + pairwise_cipher_count *
779 * PAIRWISE_CIPHER_SUITE_LEN (4) + 2 bytes akm_suite_count +
780 * akm_suite_count * AKM_SUITE_LEN (4)
781 */
782 count = *(t_u16 *)(rsn_ie + 2 + 2 + 4 * sizeof(t_u8));
783 pairwise_cipher_count = wlan_le16_to_cpu(count);
784 count = *(t_u16 *)(rsn_ie + 2 + 2 + 4 * sizeof(t_u8) + sizeof(t_u16) +
785 pairwise_cipher_count * 4);
786 akm_suite_count = wlan_le16_to_cpu(count);
787 temp = (t_u8 *)(rsn_ie + 2 + sizeof(t_u16) + 4 * sizeof(t_u8) +
788 sizeof(t_u16) + pairwise_cipher_count * 4 +
789 sizeof(t_u16));
790
791 while (akm_suite_count) {
792 if (!memcmp(pmadapter, temp, rsn_ft_1x_oui,
793 sizeof(rsn_ft_1x_oui)) ||
794 !memcmp(pmadapter, temp, rsn_ft_psk_oui,
795 sizeof(rsn_ft_psk_oui)) ||
796 !memcmp(pmadapter, temp, rsn_ft_sae_oui,
797 sizeof(rsn_ft_sae_oui))) {
798 found = 1;
799 break;
800 }
801 temp += 4;
802 akm_suite_count--;
803 }
804
805 done:
806 LEAVE();
807 return found;
808 }
809
810 /**
811 * @brief This function is to find specific IE.
812 *
813 * @param ie A pointer to ie buffer
814 * @param ie_len Length of ie buffer
815 * @param ie_type Type of ie that wants to be found in ie buffer
816 *
817 * @return MFALSE if not found; MTURE if found
818 */
wlan_find_ie(t_u8 * ie,t_u8 ie_len,t_u8 ie_type)819 static t_u8 wlan_find_ie(t_u8 *ie, t_u8 ie_len, t_u8 ie_type)
820 {
821 IEEEtypes_Header_t *pheader = MNULL;
822 t_u8 *pos = MNULL;
823 t_s8 ret_len;
824 t_u8 ret = MFALSE;
825
826 ENTER();
827
828 pos = (t_u8 *)ie;
829 ret_len = ie_len;
830 while (ret_len >= 2) {
831 pheader = (IEEEtypes_Header_t *)pos;
832 if ((t_s8)(pheader->len + sizeof(IEEEtypes_Header_t)) >
833 ret_len) {
834 PRINTM(MMSG, "invalid IE length = %d left len %d\n",
835 pheader->len, ret_len);
836 break;
837 }
838 if (pheader->element_id == ie_type) {
839 ret = MTRUE;
840 break;
841 }
842 ret_len -= pheader->len + sizeof(IEEEtypes_Header_t);
843 pos += pheader->len + sizeof(IEEEtypes_Header_t);
844 }
845
846 LEAVE();
847 return ret;
848 }
849
850 /**
851 * @brief This function prepares command of association.
852 *
853 * @param pmpriv A pointer to mlan_private structure
854 * @param cmd A pointer to HostCmd_DS_COMMAND structure
855 * @param pdata_buf A pointer cast of BSSDescriptor_t from the
856 * scan table to assoc
857 *
858 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
859 */
wlan_cmd_802_11_associate(mlan_private * pmpriv,HostCmd_DS_COMMAND * cmd,t_void * pdata_buf)860 mlan_status wlan_cmd_802_11_associate(mlan_private *pmpriv,
861 HostCmd_DS_COMMAND *cmd,
862 t_void *pdata_buf)
863 {
864 mlan_status ret = MLAN_STATUS_SUCCESS;
865 mlan_adapter *pmadapter = pmpriv->adapter;
866 HostCmd_DS_802_11_ASSOCIATE *passo = &cmd->params.associate;
867 BSSDescriptor_t *pbss_desc;
868 MrvlIEtypes_SsIdParamSet_t *pssid_tlv;
869 MrvlIEtypes_PhyParamSet_t *pphy_tlv;
870 MrvlIEtypes_SsParamSet_t *pss_tlv;
871 MrvlIEtypes_RatesParamSet_t *prates_tlv;
872 MrvlIEtypes_AuthType_t *pauth_tlv = MNULL;
873 MrvlIEtypes_RsnParamSet_t *prsn_ie_tlv = MNULL;
874 MrvlIEtypes_SAE_PWE_Mode_t *prsnx_ie_tlv = MNULL;
875 MrvlIEtypes_SecurityCfg_t *psecurity_cfg_ie = MNULL;
876 MrvlIEtypes_ChanListParamSet_t *pchan_tlv;
877 WLAN_802_11_RATES rates;
878 t_u32 rates_size;
879 t_u16 tmp_cap;
880 t_u8 *pos;
881 #ifdef DRV_EMBEDDED_SUPPLICANT
882 void *rsn_wpa_ie_tmp = MNULL;
883 #endif
884 t_u8 ft_akm = 0;
885 t_u8 oper_class;
886 t_u8 oper_class_flag = MFALSE;
887 MrvlIEtypes_HostMlme_t *host_mlme_tlv = MNULL;
888 MrvlIEtypes_PrevBssid_t *prev_bssid_tlv = MNULL;
889 t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = {0};
890
891 ENTER();
892
893 pbss_desc = (BSSDescriptor_t *)pdata_buf;
894 pos = (t_u8 *)passo;
895
896 cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE);
897
898 /* Save so we know which BSS Desc to use in the response handler */
899 pmpriv->pattempted_bss_desc = pbss_desc;
900 /* clear assoc_rsp_size */
901 pmpriv->assoc_rsp_size = 0;
902 pmpriv->assoc_req_size = 0;
903
904 memcpy_ext(pmadapter, passo->peer_sta_addr, pbss_desc->mac_address,
905 sizeof(pbss_desc->mac_address),
906 sizeof(passo->peer_sta_addr));
907 pos += sizeof(passo->peer_sta_addr);
908
909 /* Set the listen interval */
910 passo->listen_interval = wlan_cpu_to_le16(pmpriv->listen_interval);
911 /* Set the beacon period */
912 passo->beacon_period = wlan_cpu_to_le16(pbss_desc->beacon_period);
913
914 pos += sizeof(passo->cap_info);
915 pos += sizeof(passo->listen_interval);
916 pos += sizeof(passo->beacon_period);
917 pos += sizeof(passo->dtim_period);
918
919 pssid_tlv = (MrvlIEtypes_SsIdParamSet_t *)pos;
920 pssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SSID);
921 pssid_tlv->header.len = (t_u16)pbss_desc->ssid.ssid_len;
922 memcpy_ext(pmadapter, pssid_tlv->ssid, pbss_desc->ssid.ssid,
923 pssid_tlv->header.len, pssid_tlv->header.len);
924 pos += sizeof(pssid_tlv->header) + pssid_tlv->header.len;
925 pssid_tlv->header.len = wlan_cpu_to_le16(pssid_tlv->header.len);
926
927 pphy_tlv = (MrvlIEtypes_PhyParamSet_t *)pos;
928 pphy_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_PHY_DS);
929 pphy_tlv->header.len = sizeof(pphy_tlv->fh_ds.ds_param_set);
930 memcpy_ext(pmadapter, &pphy_tlv->fh_ds.ds_param_set,
931 &pbss_desc->phy_param_set.ds_param_set.current_chan,
932 sizeof(pphy_tlv->fh_ds.ds_param_set),
933 sizeof(pphy_tlv->fh_ds.ds_param_set));
934 pos += sizeof(pphy_tlv->header) + pphy_tlv->header.len;
935 pphy_tlv->header.len = wlan_cpu_to_le16(pphy_tlv->header.len);
936
937 pss_tlv = (MrvlIEtypes_SsParamSet_t *)pos;
938 pss_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CF);
939 pss_tlv->header.len = sizeof(pss_tlv->cf_ibss.cf_param_set);
940 pos += sizeof(pss_tlv->header) + pss_tlv->header.len;
941 pss_tlv->header.len = wlan_cpu_to_le16(pss_tlv->header.len);
942
943 /* Get the common rates supported between the driver and the BSS Desc */
944 if (wlan_setup_rates_from_bssdesc(pmpriv, pbss_desc, rates,
945 &rates_size)) {
946 ret = MLAN_STATUS_FAILURE;
947 goto done;
948 }
949
950 /* Save the data rates into Current BSS state structure */
951 pmpriv->curr_bss_params.num_of_rates = rates_size;
952 memcpy_ext(pmadapter, &pmpriv->curr_bss_params.data_rates, rates,
953 rates_size, WLAN_SUPPORTED_RATES);
954
955 /* Setup the Rates TLV in the association command */
956 prates_tlv = (MrvlIEtypes_RatesParamSet_t *)pos;
957 prates_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_RATES);
958 prates_tlv->header.len = wlan_cpu_to_le16((t_u16)rates_size);
959 memcpy_ext(pmadapter, prates_tlv->rates, rates, rates_size, rates_size);
960 pos += sizeof(prates_tlv->header) + rates_size;
961 PRINTM(MINFO, "ASSOC_CMD: Rates size = %d\n", rates_size);
962
963 /* Add the Authentication type to be used for Auth frames if needed */
964 if ((pmpriv->sec_info.authentication_mode != MLAN_AUTH_MODE_AUTO)) {
965 pauth_tlv = (MrvlIEtypes_AuthType_t *)pos;
966 pauth_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_AUTH_TYPE);
967 pauth_tlv->header.len = sizeof(pauth_tlv->auth_type);
968 if ((pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled) ||
969 (pmpriv->sec_info.authentication_mode ==
970 MLAN_AUTH_MODE_NETWORKEAP))
971 pauth_tlv->auth_type = wlan_cpu_to_le16(
972 (t_u16)pmpriv->sec_info.authentication_mode);
973 else if (pmpriv->sec_info.authentication_mode ==
974 MLAN_AUTH_MODE_FT)
975 pauth_tlv->auth_type =
976 wlan_cpu_to_le16(AssocAgentAuth_FastBss_Skip);
977 else if (pmpriv->sec_info.authentication_mode ==
978 MLAN_AUTH_MODE_SAE)
979 pauth_tlv->auth_type =
980 wlan_cpu_to_le16(AssocAgentAuth_Wpa3Sae);
981 else
982 pauth_tlv->auth_type =
983 wlan_cpu_to_le16(MLAN_AUTH_MODE_OPEN);
984 pos += sizeof(pauth_tlv->header) + pauth_tlv->header.len;
985 pauth_tlv->header.len = wlan_cpu_to_le16(pauth_tlv->header.len);
986 }
987
988 if ((pauth_tlv != MNULL) &&
989 (pauth_tlv->auth_type ==
990 wlan_cpu_to_le16(AssocAgentAuth_Wpa3Sae))) {
991 if (pbss_desc->prsnx_ie && pbss_desc->prsnx_ie->ieee_hdr.len &&
992 (pbss_desc->prsnx_ie->data[0] & (0x1 << SAE_H2E_BIT))) {
993 MrvlIEtypes_SAE_PWE_Mode_t *psae_pwe_mode_tlv;
994
995 /* Setup the sae pwe derivation mode TLV in the
996 * association command */
997 psae_pwe_mode_tlv = (MrvlIEtypes_SAE_PWE_Mode_t *)pos;
998 psae_pwe_mode_tlv->header.type = wlan_cpu_to_le16(
999 TLV_TYPE_WPA3_SAE_PWE_DERIVATION_MODE);
1000 psae_pwe_mode_tlv->header.len =
1001 sizeof(psae_pwe_mode_tlv->pwe);
1002 psae_pwe_mode_tlv->pwe[0] =
1003 pbss_desc->prsnx_ie->data[0];
1004 pos += sizeof(psae_pwe_mode_tlv->header) +
1005 sizeof(psae_pwe_mode_tlv->pwe);
1006 }
1007 }
1008
1009 if (IS_SUPPORT_MULTI_BANDS(pmadapter) &&
1010 (pbss_desc->bss_band & pmpriv->config_bands) &&
1011 !(ISSUPP_11NENABLED(pmadapter->fw_cap_info) &&
1012 (!pbss_desc->disable_11n) &&
1013 (pmpriv->config_bands & BAND_GN ||
1014 pmpriv->config_bands & BAND_AN) &&
1015 (pbss_desc->pht_cap))) {
1016 /* Append a channel TLV for the channel the attempted AP was
1017 * found on */
1018 pchan_tlv = (MrvlIEtypes_ChanListParamSet_t *)pos;
1019 pchan_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
1020 pchan_tlv->header.len =
1021 wlan_cpu_to_le16(sizeof(ChanScanParamSet_t));
1022
1023 memset(pmadapter, pchan_tlv->chan_scan_param, 0x00,
1024 sizeof(ChanScanParamSet_t));
1025 pchan_tlv->chan_scan_param[0].chan_number =
1026 (pbss_desc->phy_param_set.ds_param_set.current_chan);
1027 PRINTM(MINFO, "Assoc: TLV Chan = %d\n",
1028 pchan_tlv->chan_scan_param[0].chan_number);
1029
1030 pchan_tlv->chan_scan_param[0].bandcfg.chanBand =
1031 wlan_band_to_radio_type(pbss_desc->bss_band);
1032 PRINTM(MINFO, "Assoc: TLV Bandcfg = %x\n",
1033 pchan_tlv->chan_scan_param[0].bandcfg);
1034 pos += sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
1035 }
1036 if (!pmpriv->wps.session_enable) {
1037 if ((pmpriv->sec_info.wpa_enabled ||
1038 pmpriv->sec_info.wpa2_enabled)) {
1039 prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
1040 /* WPA_IE or RSN_IE */
1041 prsn_ie_tlv->header.type = (t_u16)pmpriv->wpa_ie[0];
1042 prsn_ie_tlv->header.type =
1043 prsn_ie_tlv->header.type & 0x00FF;
1044 prsn_ie_tlv->header.type =
1045 wlan_cpu_to_le16(prsn_ie_tlv->header.type);
1046 prsn_ie_tlv->header.len = (t_u16)pmpriv->wpa_ie[1];
1047 prsn_ie_tlv->header.len =
1048 prsn_ie_tlv->header.len & 0x00FF;
1049 if (prsn_ie_tlv->header.len <=
1050 (sizeof(pmpriv->wpa_ie) - 2))
1051 memcpy_ext(pmadapter, prsn_ie_tlv->rsn_ie,
1052 &pmpriv->wpa_ie[2],
1053 prsn_ie_tlv->header.len,
1054 prsn_ie_tlv->header.len);
1055 else {
1056 ret = MLAN_STATUS_FAILURE;
1057 goto done;
1058 }
1059 HEXDUMP("ASSOC_CMD: RSN IE", (t_u8 *)prsn_ie_tlv,
1060 sizeof(prsn_ie_tlv->header) +
1061 prsn_ie_tlv->header.len);
1062 pos += sizeof(prsn_ie_tlv->header) +
1063 prsn_ie_tlv->header.len;
1064 prsn_ie_tlv->header.len =
1065 wlan_cpu_to_le16(prsn_ie_tlv->header.len);
1066 /** parse rsn ie to find whether ft akm is used*/
1067 ft_akm = wlan_ft_akm_is_used(pmpriv, pmpriv->wpa_ie);
1068 /* Append PMF Configuration coming from cfg80211 layer
1069 */
1070 psecurity_cfg_ie = (MrvlIEtypes_SecurityCfg_t *)pos;
1071 psecurity_cfg_ie->header.type =
1072 wlan_cpu_to_le16(TLV_TYPE_SECURITY_CFG);
1073
1074 pmpriv->curr_bss_params.use_mfp =
1075 wlan_use_mfp(pmpriv, pbss_desc);
1076 PRINTM(MCMND, "use_mfp=%d\n",
1077 pmpriv->curr_bss_params.use_mfp);
1078
1079 if (!pmpriv->curr_bss_params.use_mfp)
1080 psecurity_cfg_ie->use_mfp = MFALSE;
1081 else
1082 psecurity_cfg_ie->use_mfp = MTRUE;
1083 psecurity_cfg_ie->header.len = sizeof(t_u8);
1084 pos += sizeof(psecurity_cfg_ie->header) +
1085 psecurity_cfg_ie->header.len;
1086 }
1087 #ifdef DRV_EMBEDDED_SUPPLICANT
1088 else if (supplicantIsEnabled(pmpriv->psapriv)) {
1089 supplicantClrEncryptKey(pmpriv->psapriv);
1090
1091 if (pbss_desc->prsn_ie)
1092 rsn_wpa_ie_tmp = pbss_desc->prsn_ie;
1093 else if (pbss_desc->pwpa_ie)
1094 rsn_wpa_ie_tmp = pbss_desc->pwpa_ie;
1095 prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
1096 pos += supplicantFormatRsnWpaTlv(
1097 pmpriv->psapriv, rsn_wpa_ie_tmp, prsn_ie_tlv);
1098 }
1099 #endif
1100 else if (pmpriv->sec_info.ewpa_enabled) {
1101 prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
1102 if (pbss_desc->pwpa_ie) {
1103 prsn_ie_tlv->header.type =
1104 (t_u16)(*(pbss_desc->pwpa_ie))
1105 .vend_hdr.element_id;
1106 prsn_ie_tlv->header.type =
1107 prsn_ie_tlv->header.type & 0x00FF;
1108 prsn_ie_tlv->header.type = wlan_cpu_to_le16(
1109 prsn_ie_tlv->header.type);
1110 prsn_ie_tlv->header.len =
1111 (t_u16)(*(pbss_desc->pwpa_ie))
1112 .vend_hdr.len;
1113 prsn_ie_tlv->header.len =
1114 prsn_ie_tlv->header.len & 0x00FF;
1115 if (prsn_ie_tlv->header.len <=
1116 (sizeof(pmpriv->wpa_ie))) {
1117 memcpy_ext(pmadapter,
1118 prsn_ie_tlv->rsn_ie,
1119 &((*(pbss_desc->pwpa_ie))
1120 .vend_hdr.oui[0]),
1121 prsn_ie_tlv->header.len,
1122 prsn_ie_tlv->header.len);
1123 } else {
1124 ret = MLAN_STATUS_FAILURE;
1125 goto done;
1126 }
1127
1128 HEXDUMP("ASSOC_CMD: RSN IE",
1129 (t_u8 *)prsn_ie_tlv,
1130 sizeof(prsn_ie_tlv->header) +
1131 prsn_ie_tlv->header.len);
1132 pos += sizeof(prsn_ie_tlv->header) +
1133 prsn_ie_tlv->header.len;
1134 prsn_ie_tlv->header.len = wlan_cpu_to_le16(
1135 prsn_ie_tlv->header.len);
1136 }
1137 if (pbss_desc->prsn_ie) {
1138 prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
1139 prsn_ie_tlv->header.type =
1140 (t_u16)(*(pbss_desc->prsn_ie))
1141 .ieee_hdr.element_id;
1142 prsn_ie_tlv->header.type =
1143 prsn_ie_tlv->header.type & 0x00FF;
1144 prsn_ie_tlv->header.type = wlan_cpu_to_le16(
1145 prsn_ie_tlv->header.type);
1146 prsn_ie_tlv->header.len =
1147 (t_u16)(*(pbss_desc->prsn_ie))
1148 .ieee_hdr.len;
1149 prsn_ie_tlv->header.len =
1150 prsn_ie_tlv->header.len & 0x00FF;
1151 if (prsn_ie_tlv->header.len <=
1152 (sizeof(pmpriv->wpa_ie))) {
1153 memcpy_ext(pmadapter,
1154 prsn_ie_tlv->rsn_ie,
1155 &((*(pbss_desc->prsn_ie))
1156 .data[0]),
1157 prsn_ie_tlv->header.len,
1158 prsn_ie_tlv->header.len);
1159 ret = wlan_update_rsn_ie(pmpriv,
1160 prsn_ie_tlv);
1161 if (ret != MLAN_STATUS_SUCCESS) {
1162 goto done;
1163 }
1164 } else {
1165 ret = MLAN_STATUS_FAILURE;
1166 goto done;
1167 }
1168
1169 HEXDUMP("ASSOC_CMD: RSN IE",
1170 (t_u8 *)prsn_ie_tlv,
1171 sizeof(prsn_ie_tlv->header) +
1172 prsn_ie_tlv->header.len);
1173 pos += sizeof(prsn_ie_tlv->header) +
1174 prsn_ie_tlv->header.len;
1175 prsn_ie_tlv->header.len = wlan_cpu_to_le16(
1176 prsn_ie_tlv->header.len);
1177 }
1178 if (pbss_desc->prsnx_ie) {
1179 prsnx_ie_tlv =
1180 (MrvlIEtypes_SAE_PWE_Mode_t *)pos;
1181 prsnx_ie_tlv->header.type =
1182 (t_u16)(*(pbss_desc->prsnx_ie))
1183 .ieee_hdr.element_id;
1184 prsnx_ie_tlv->header.type =
1185 prsnx_ie_tlv->header.type & 0x00FF;
1186 prsnx_ie_tlv->header.type = wlan_cpu_to_le16(
1187 prsnx_ie_tlv->header.type);
1188 prsnx_ie_tlv->header.len =
1189 (t_u16)(*(pbss_desc->prsnx_ie))
1190 .ieee_hdr.len;
1191 prsnx_ie_tlv->header.len =
1192 prsnx_ie_tlv->header.len & 0x00FF;
1193
1194 memcpy_ext(pmadapter, prsnx_ie_tlv->pwe,
1195 &((*(pbss_desc->prsnx_ie)).data[0]),
1196 prsnx_ie_tlv->header.len,
1197 prsnx_ie_tlv->header.len);
1198
1199 HEXDUMP("ASSOC_CMD: RSNX IE",
1200 (t_u8 *)prsnx_ie_tlv,
1201 sizeof(prsnx_ie_tlv->header) +
1202 prsnx_ie_tlv->header.len);
1203
1204 pos += sizeof(prsnx_ie_tlv->header) +
1205 prsnx_ie_tlv->header.len;
1206 prsnx_ie_tlv->header.len = wlan_cpu_to_le16(
1207 prsnx_ie_tlv->header.len);
1208 }
1209 }
1210 }
1211
1212 if (ISSUPP_11NENABLED(pmadapter->fw_cap_info) &&
1213 (!pbss_desc->disable_11n) &&
1214 wlan_11n_bandconfig_allowed(pmpriv, pbss_desc->bss_band))
1215 wlan_cmd_append_11n_tlv(pmpriv, pbss_desc, &pos);
1216 else if ((pmpriv->hotspot_cfg & HOTSPOT_ENABLED) &&
1217 !(pmpriv->hotspot_cfg & HOTSPOT_BY_SUPPLICANT))
1218 wlan_add_ext_capa_info_ie(pmpriv, pbss_desc, &pos);
1219 if (pmpriv->adapter->ecsa_enable) {
1220 oper_class_flag =
1221 wlan_find_ie(pmpriv->gen_ie_buf, pmpriv->gen_ie_buf_len,
1222 REGULATORY_CLASS);
1223 if (!oper_class_flag) {
1224 if (MLAN_STATUS_SUCCESS ==
1225 wlan_get_curr_oper_class(
1226 pmpriv,
1227 pbss_desc->phy_param_set.ds_param_set
1228 .current_chan,
1229 pbss_desc->curr_bandwidth, &oper_class))
1230 wlan_add_supported_oper_class_ie(pmpriv, &pos,
1231 oper_class);
1232 }
1233 }
1234 if (ISSUPP_11ACENABLED(pmadapter->fw_cap_info) &&
1235 (!pbss_desc->disable_11n) &&
1236 wlan_11ac_bandconfig_allowed(pmpriv, pbss_desc->bss_band))
1237 wlan_cmd_append_11ac_tlv(pmpriv, pbss_desc, &pos);
1238
1239 if ((IS_FW_SUPPORT_11AX(pmadapter)) &&
1240 wlan_11ax_bandconfig_allowed(pmpriv, pbss_desc))
1241 wlan_cmd_append_11ax_tlv(pmpriv, pbss_desc, &pos);
1242
1243 wlan_wmm_process_association_req(pmpriv, &pos, &pbss_desc->wmm_ie);
1244 if (pmpriv->sec_info.wapi_enabled && pmpriv->wapi_ie_len)
1245 wlan_cmd_append_wapi_ie(pmpriv, &pos);
1246
1247 if (pmpriv->sec_info.osen_enabled && pmpriv->osen_ie_len)
1248 wlan_cmd_append_osen_ie(pmpriv, &pos);
1249
1250 wlan_cmd_append_generic_ie(pmpriv, &pos);
1251
1252 if (ft_akm && pbss_desc->pmd_ie)
1253 wlan_cmd_append_pass_through_ie(
1254 pmpriv, (IEEEtypes_Generic_t *)pbss_desc->pmd_ie, &pos);
1255 wlan_cmd_append_tsf_tlv(pmpriv, &pos, pbss_desc);
1256
1257 if (pmpriv->curr_bss_params.host_mlme) {
1258 host_mlme_tlv = (MrvlIEtypes_HostMlme_t *)pos;
1259 host_mlme_tlv->header.type =
1260 wlan_cpu_to_le16(TLV_TYPE_HOST_MLME);
1261 host_mlme_tlv->header.len =
1262 wlan_cpu_to_le16(sizeof(host_mlme_tlv->host_mlme));
1263 host_mlme_tlv->host_mlme = MTRUE;
1264 pos += sizeof(host_mlme_tlv->header) +
1265 host_mlme_tlv->header.len;
1266 }
1267 if (memcmp(pmadapter, &pmpriv->curr_bss_params.prev_bssid, zero_mac,
1268 MLAN_MAC_ADDR_LENGTH)) {
1269 prev_bssid_tlv = (MrvlIEtypes_PrevBssid_t *)pos;
1270 prev_bssid_tlv->header.type =
1271 wlan_cpu_to_le16(TLV_TYPE_PREV_BSSID);
1272 prev_bssid_tlv->header.len = MLAN_MAC_ADDR_LENGTH;
1273 memcpy_ext(pmadapter, prev_bssid_tlv->prev_bssid,
1274 &pmpriv->curr_bss_params.prev_bssid,
1275 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
1276 PRINTM(MCMND, "ASSOCIATE: PREV_BSSID = " MACSTR "\n",
1277 MAC2STR(pmpriv->curr_bss_params.prev_bssid));
1278 pos += sizeof(prev_bssid_tlv->header) + MLAN_MAC_ADDR_LENGTH;
1279 }
1280
1281 if (wlan_11d_create_dnld_countryinfo(pmpriv, pbss_desc->bss_band)) {
1282 PRINTM(MERROR, "Dnld_countryinfo_11d failed\n");
1283 ret = MLAN_STATUS_FAILURE;
1284 goto done;
1285 }
1286 if (wlan_11d_parse_dnld_countryinfo(pmpriv,
1287 pmpriv->pattempted_bss_desc)) {
1288 ret = MLAN_STATUS_FAILURE;
1289 goto done;
1290 }
1291
1292 /*
1293 * Call 11h join API after capability bits are set so adhoc/infra 11h
1294 * behavior can be properly triggered. pos modified if data is appended
1295 */
1296 wlan_11h_process_join(
1297 pmpriv, &pos, &passo->cap_info, (t_u8)pbss_desc->bss_band,
1298 pbss_desc->phy_param_set.ds_param_set.current_chan,
1299 &pbss_desc->wlan_11h_bss_info);
1300
1301 cmd->size = wlan_cpu_to_le16((t_u16)(pos - (t_u8 *)passo) + S_DS_GEN);
1302
1303 /* Set the Capability info at last */
1304 memcpy_ext(pmadapter, &tmp_cap, &pbss_desc->cap_info,
1305 sizeof(passo->cap_info), sizeof(tmp_cap));
1306
1307 if (pmpriv->config_bands == BAND_B)
1308 SHORT_SLOT_TIME_DISABLED(tmp_cap);
1309
1310 tmp_cap &= CAPINFO_MASK;
1311 PRINTM(MINFO, "ASSOC_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n", tmp_cap,
1312 CAPINFO_MASK);
1313 tmp_cap = wlan_cpu_to_le16(tmp_cap);
1314 memcpy_ext(pmadapter, &passo->cap_info, &tmp_cap, sizeof(tmp_cap),
1315 sizeof(passo->cap_info));
1316
1317 done:
1318 LEAVE();
1319 return ret;
1320 }
1321
1322 /**
1323 * @brief Association firmware command response handler
1324 *
1325 * The response buffer for the association command has the following
1326 * memory layout.
1327 *
1328 * For cases where an association response was not received (indicated
1329 * by the CapInfo and AId field):
1330 *
1331 * .------------------------------------------------------------.
1332 * | Header(4 * sizeof(t_u16)): Standard command response hdr |
1333 * .------------------------------------------------------------.
1334 * | cap_info/Error Return(t_u16): |
1335 * | 0xFFFF(-1): Internal error for association |
1336 * | 0xFFFE(-2): Authentication unhandled message |
1337 * | 0xFFFD(-3): Authentication refused |
1338 * | 0xFFFC(-4): Timeout waiting for AP response |
1339 * | 0xFFFB(-5): Internal error for authentication |
1340 * .------------------------------------------------------------.
1341 * | status_code(t_u16): |
1342 * | If cap_info is -1: |
1343 * | An internal firmware failure prevented the |
1344 * | command from being processed. The status code |
1345 * | is 6 if associate response parameter invlaid, |
1346 * | 1 otherwise. |
1347 * | |
1348 * | If cap_info is -2: |
1349 * | An authentication frame was received but was |
1350 * | not handled by the firmware. IEEE Status code |
1351 * | for the failure is returned. |
1352 * | |
1353 * | If cap_info is -3: |
1354 * | An authentication frame was received and the |
1355 * | status_code is the IEEE Status reported in the |
1356 * | response. |
1357 * | |
1358 * | If cap_info is -4: |
1359 * | (1) Association response timeout |
1360 * | (2) Authentication response timeout |
1361 * | |
1362 * | If cap_info is -5: |
1363 * | An internal firmware failure prevented the |
1364 * | command from being processed. The status code |
1365 * | is 6 if authentication parameter invlaid, |
1366 * | 1 otherwise. |
1367 * .------------------------------------------------------------.
1368 * | a_id(t_u16): 0xFFFF |
1369 * .------------------------------------------------------------.
1370 *
1371 *
1372 * For cases where an association response was received, the IEEE
1373 * standard association response frame is returned:
1374 *
1375 * .------------------------------------------------------------.
1376 * | Header(4 * sizeof(t_u16)): Standard command response hdr |
1377 * .------------------------------------------------------------.
1378 * | cap_info(t_u16): IEEE Capability |
1379 * .------------------------------------------------------------.
1380 * | status_code(t_u16): IEEE Status Code |
1381 * .------------------------------------------------------------.
1382 * | a_id(t_u16): IEEE Association ID |
1383 * .------------------------------------------------------------.
1384 * | IEEE IEs(variable): Any received IEs comprising the |
1385 * | remaining portion of a received |
1386 * | association response frame. |
1387 * .------------------------------------------------------------.
1388 *
1389 * For simplistic handling, the status_code field can be used to determine
1390 * an association success (0) or failure (non-zero).
1391 *
1392 * @param pmpriv A pointer to mlan_private structure
1393 * @param resp A pointer to HostCmd_DS_COMMAND
1394 * @param pioctl_buf A pointer to mlan_ioctl_req structure
1395 *
1396 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1397 */
wlan_ret_802_11_associate(mlan_private * pmpriv,HostCmd_DS_COMMAND * resp,t_void * pioctl_buf)1398 mlan_status wlan_ret_802_11_associate(mlan_private *pmpriv,
1399 HostCmd_DS_COMMAND *resp,
1400 t_void *pioctl_buf)
1401 {
1402 mlan_status ret = MLAN_STATUS_SUCCESS;
1403 mlan_ioctl_req *pioctl_req = (mlan_ioctl_req *)pioctl_buf;
1404 IEEEtypes_AssocRsp_t *passoc_rsp;
1405 BSSDescriptor_t *pbss_desc;
1406 t_u8 enable_data = MTRUE;
1407 t_u8 event_buf[100];
1408 mlan_event *pevent = (mlan_event *)event_buf;
1409 t_u8 cur_mac[MLAN_MAC_ADDR_LENGTH];
1410 t_u8 media_connected = pmpriv->media_connected;
1411 mlan_adapter *pmadapter = pmpriv->adapter;
1412 assoc_logger_data *assoc_succ;
1413 mlan_ds_bss *bss;
1414 IEEEtypes_MgmtHdr_t *hdr;
1415
1416 ENTER();
1417
1418 if (pmpriv->curr_bss_params.host_mlme) {
1419 hdr = (IEEEtypes_MgmtHdr_t *)&resp->params;
1420 if (!memcmp(pmpriv->adapter, hdr->BssId,
1421 pmpriv->pattempted_bss_desc->mac_address,
1422 MLAN_MAC_ADDR_LENGTH))
1423 passoc_rsp = (IEEEtypes_AssocRsp_t
1424 *)((t_u8 *)(&resp->params) +
1425 sizeof(IEEEtypes_MgmtHdr_t));
1426 else
1427 passoc_rsp = (IEEEtypes_AssocRsp_t *)&resp->params;
1428 } else
1429
1430 passoc_rsp = (IEEEtypes_AssocRsp_t *)&resp->params;
1431 passoc_rsp->status_code = wlan_le16_to_cpu(passoc_rsp->status_code);
1432 if (pmpriv->media_connected == MTRUE)
1433 memcpy_ext(pmpriv->adapter, cur_mac,
1434 pmpriv->curr_bss_params.bss_descriptor.mac_address,
1435 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
1436
1437 HEXDUMP("ASSOC_RESP:", (t_u8 *)&resp->params, (resp->size - S_DS_GEN));
1438
1439 pmpriv->assoc_rsp_size =
1440 MIN(resp->size - S_DS_GEN, sizeof(pmpriv->assoc_rsp_buf));
1441
1442 memcpy_ext(pmpriv->adapter, pmpriv->assoc_rsp_buf, &resp->params,
1443 pmpriv->assoc_rsp_size, pmpriv->assoc_rsp_size);
1444
1445 if (pioctl_req != MNULL) {
1446 bss = (mlan_ds_bss *)pioctl_req->pbuf;
1447 bss->param.ssid_bssid.assoc_rsp.assoc_resp_len =
1448 pmpriv->assoc_rsp_size;
1449 memcpy_ext(pmpriv->adapter,
1450 bss->param.ssid_bssid.assoc_rsp.assoc_resp_buf,
1451 pmpriv->assoc_rsp_buf, pmpriv->assoc_rsp_size,
1452 ASSOC_RSP_BUF_SIZE);
1453 }
1454 if (passoc_rsp->status_code) {
1455 if (pmpriv->media_connected == MTRUE) {
1456 if (pmpriv->port_ctrl_mode == MTRUE)
1457 pmpriv->port_open = pmpriv->prior_port_status;
1458 if (!memcmp(pmpriv->adapter, cur_mac,
1459 pmpriv->pattempted_bss_desc->mac_address,
1460 MLAN_MAC_ADDR_LENGTH))
1461 wlan_reset_connect_state(pmpriv, MTRUE);
1462 else
1463 wlan_recv_event(
1464 pmpriv,
1465 MLAN_EVENT_ID_DRV_ASSOC_FAILURE_REPORT,
1466 MNULL);
1467 } else
1468 wlan_reset_connect_state(pmpriv, MTRUE);
1469 pmpriv->adapter->dbg.num_cmd_assoc_failure++;
1470 pmpriv->adapter->dbg.num_cons_assoc_failure++;
1471 PRINTM(MERROR,
1472 "ASSOC_RESP: Association Failed, "
1473 "status code = %d, error = 0x%x, a_id = 0x%x\n",
1474 passoc_rsp->status_code,
1475 wlan_le16_to_cpu(*(t_u16 *)&passoc_rsp->capability),
1476 wlan_le16_to_cpu(passoc_rsp->a_id));
1477 memset(pmadapter, event_buf, 0, sizeof(event_buf));
1478 pevent->bss_index = pmpriv->bss_index;
1479 pevent->event_id = MLAN_EVENT_ID_DRV_ASSOC_FAILURE_LOGGER;
1480 pevent->event_len = sizeof(passoc_rsp->status_code);
1481 memcpy_ext(pmpriv->adapter, (t_u8 *)pevent->event_buf,
1482 &passoc_rsp->status_code, pevent->event_len,
1483 pevent->event_len);
1484 wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_ASSOC_FAILURE_LOGGER,
1485 pevent);
1486
1487 ret = MLAN_STATUS_FAILURE;
1488 goto done;
1489 }
1490
1491 /* Send a Media Connected event, according to the Spec */
1492 pmpriv->media_connected = MTRUE;
1493 pmpriv->adapter->pps_uapsd_mode = MFALSE;
1494 pmpriv->adapter->tx_lock_flag = MFALSE;
1495 pmpriv->adapter->delay_null_pkt = MFALSE;
1496
1497 /* Set the attempted BSSID Index to current */
1498 pbss_desc = pmpriv->pattempted_bss_desc;
1499
1500 PRINTM(MCMND, "ASSOC_RESP: %-32s (a_id = 0x%x)\n", pbss_desc->ssid.ssid,
1501 wlan_le16_to_cpu(passoc_rsp->a_id));
1502 /* Restore default extended capabilities */
1503 memcpy_ext(pmpriv->adapter, &pmpriv->ext_cap, &pmpriv->def_ext_cap,
1504 sizeof(pmpriv->ext_cap), sizeof(pmpriv->ext_cap));
1505 /* Make a copy of current BSSID descriptor */
1506 memcpy_ext(pmpriv->adapter, &pmpriv->curr_bss_params.bss_descriptor,
1507 pbss_desc, sizeof(BSSDescriptor_t), sizeof(BSSDescriptor_t));
1508
1509 /* Update curr_bss_params */
1510 pmpriv->curr_bss_params.bss_descriptor.channel =
1511 pbss_desc->phy_param_set.ds_param_set.current_chan;
1512
1513 pmpriv->curr_bss_params.band = pbss_desc->bss_band;
1514
1515 /* Store current channel for further reference.
1516 * This would save one extra call to get current
1517 * channel when disconnect/bw_ch event is raised.
1518 */
1519 pmpriv->adapter->dfsr_channel =
1520 pmpriv->curr_bss_params.bss_descriptor.channel;
1521
1522 /*`
1523 * Adjust the timestamps in the scan table to be relative to the newly
1524 * associated AP's TSF
1525 */
1526 wlan_update_tsf_timestamps(pmpriv, pbss_desc);
1527
1528 if (pbss_desc->wmm_ie.vend_hdr.element_id == WMM_IE)
1529 pmpriv->curr_bss_params.wmm_enabled = MTRUE;
1530 else
1531 pmpriv->curr_bss_params.wmm_enabled = MFALSE;
1532
1533 if (pmpriv->wmm_required && pmpriv->curr_bss_params.wmm_enabled)
1534 pmpriv->wmm_enabled = MTRUE;
1535 else
1536 pmpriv->wmm_enabled = MFALSE;
1537
1538 pmpriv->curr_bss_params.wmm_uapsd_enabled = MFALSE;
1539
1540 if (pmpriv->wmm_enabled == MTRUE)
1541 pmpriv->curr_bss_params.wmm_uapsd_enabled =
1542 pbss_desc->wmm_ie.qos_info.qos_uapsd;
1543
1544 PRINTM(MINFO, "ASSOC_RESP: curr_pkt_filter is 0x%x\n",
1545 pmpriv->curr_pkt_filter);
1546 if (pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.wpa2_enabled)
1547 pmpriv->wpa_is_gtk_set = MFALSE;
1548 if (pmpriv->wmm_enabled)
1549 /* Don't re-enable carrier until we get the WMM_GET_STATUS event
1550 */
1551 enable_data = MFALSE;
1552 else
1553 /* Since WMM is not enabled, setup the queues with the defaults
1554 */
1555 wlan_wmm_setup_queues(pmpriv);
1556
1557 if (enable_data)
1558 PRINTM(MINFO, "Post association, re-enabling data flow\n");
1559
1560 /* Reset SNR/NF/RSSI values */
1561 pmpriv->data_rssi_last = 0;
1562 pmpriv->data_nf_last = 0;
1563 pmpriv->data_rssi_avg = 0;
1564 pmpriv->data_nf_avg = 0;
1565 pmpriv->bcn_rssi_last = 0;
1566 pmpriv->bcn_nf_last = 0;
1567 pmpriv->bcn_rssi_avg = 0;
1568 pmpriv->bcn_nf_avg = 0;
1569 pmpriv->rxpd_rate = 0;
1570 pmpriv->rxpd_rate_info = 0;
1571 /* Reset mib statistics*/
1572 pmpriv->amsdu_rx_cnt = 0;
1573 pmpriv->amsdu_tx_cnt = 0;
1574 pmpriv->msdu_in_rx_amsdu_cnt = 0;
1575 pmpriv->msdu_in_tx_amsdu_cnt = 0;
1576 if (pbss_desc->pvht_cap && pbss_desc->pht_cap) {
1577 if (GET_VHTCAP_MAXMPDULEN(
1578 pbss_desc->pvht_cap->vht_cap.vht_cap_info) == 2)
1579 pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_12K;
1580 else if (GET_VHTCAP_MAXMPDULEN(
1581 pbss_desc->pvht_cap->vht_cap.vht_cap_info) ==
1582 1)
1583 pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_8K;
1584 else
1585 pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_4K;
1586 } else if (pbss_desc->pht_cap) {
1587 if (GETHT_MAXAMSDU(pbss_desc->pht_cap->ht_cap.ht_cap_info))
1588 pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_8K;
1589 else
1590 pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_4K;
1591 }
1592
1593 wlan_save_curr_bcn(pmpriv);
1594
1595 pmpriv->adapter->dbg.num_cmd_assoc_success++;
1596 pmpriv->adapter->dbg.num_cons_assoc_failure = 0;
1597 PRINTM(MINFO, "ASSOC_RESP: Associated\n");
1598 pevent->bss_index = pmpriv->bss_index;
1599 pevent->event_id = MLAN_EVENT_ID_DRV_CONNECTED;
1600 pevent->event_len = MLAN_MAC_ADDR_LENGTH;
1601 memcpy_ext(pmpriv->adapter, (t_u8 *)pevent->event_buf,
1602 (t_u8 *)pmpriv->curr_bss_params.bss_descriptor.mac_address,
1603 MLAN_MAC_ADDR_LENGTH, pevent->event_len);
1604
1605 /* Add the ra_list here for infra mode as there will be only 1 ra always
1606 */
1607 if (media_connected) {
1608 /** replace ralist's mac address with new mac address */
1609 if (0 ==
1610 wlan_ralist_update(
1611 pmpriv, cur_mac,
1612 pmpriv->curr_bss_params.bss_descriptor.mac_address))
1613 wlan_ralist_add(pmpriv,
1614 pmpriv->curr_bss_params.bss_descriptor
1615 .mac_address);
1616 wlan_11n_cleanup_reorder_tbl(pmpriv);
1617 wlan_11n_deleteall_txbastream_tbl(pmpriv);
1618
1619 } else
1620 wlan_ralist_add(
1621 pmpriv,
1622 pmpriv->curr_bss_params.bss_descriptor.mac_address);
1623
1624 wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_CONNECTED, pevent);
1625 #ifdef UAP_SUPPORT
1626 if (pmpriv->adapter->dfs_mode)
1627 wlan_11h_update_dfs_master_state_by_sta(pmpriv);
1628 #endif
1629
1630 wlan_coex_ampdu_rxwinsize(pmpriv->adapter);
1631
1632 if (!pmpriv->sec_info.wpa_enabled && !pmpriv->sec_info.wpa2_enabled &&
1633 !pmpriv->sec_info.ewpa_enabled && !pmpriv->sec_info.wapi_enabled &&
1634 !pmpriv->wps.session_enable && !pmpriv->sec_info.osen_enabled
1635 #ifdef DRV_EMBEDDED_SUPPLICANT
1636 && !supplicantIsEnabled(pmpriv->psapriv)
1637 #endif
1638 ) {
1639 /* We are in Open/WEP mode, open port immediately */
1640 if (pmpriv->port_ctrl_mode == MTRUE) {
1641 pmpriv->port_open = MTRUE;
1642 PRINTM(MINFO, "ASSOC_RESP: port_status = OPEN\n");
1643 }
1644 }
1645 if (pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.wpa2_enabled ||
1646 pmpriv->sec_info.ewpa_enabled || pmpriv->sec_info.wapi_enabled ||
1647 pmpriv->wps.session_enable || pmpriv->sec_info.osen_enabled
1648 #ifdef DRV_EMBEDDED_SUPPLICANT
1649 || (supplicantIsEnabled(pmpriv->psapriv))
1650 #endif
1651 )
1652 pmpriv->adapter->scan_block = MTRUE;
1653
1654 #ifdef DRV_EMBEDDED_SUPPLICANT
1655 supplicantInitSession(
1656 pmpriv->psapriv,
1657 (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor.ssid.ssid,
1658 pmpriv->curr_bss_params.bss_descriptor.ssid.ssid_len,
1659 (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor.mac_address,
1660 (t_u8 *)&pmpriv->curr_addr);
1661 #endif
1662
1663 pevent = (mlan_event *)event_buf;
1664 memset(pmadapter, event_buf, 0, sizeof(event_buf));
1665 pevent->bss_index = pmpriv->bss_index;
1666 pevent->event_id = MLAN_EVENT_ID_DRV_ASSOC_SUCC_LOGGER;
1667 pevent->event_len = sizeof(assoc_logger_data);
1668 assoc_succ = (assoc_logger_data *)pevent->event_buf;
1669 memcpy_ext(pmpriv->adapter, (t_u8 *)assoc_succ->bssid,
1670 pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH,
1671 MLAN_MAC_ADDR_LENGTH);
1672 memcpy_ext(pmpriv->adapter, (t_u8 *)assoc_succ->oui,
1673 pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH / 2,
1674 MLAN_MAC_ADDR_LENGTH / 2);
1675 memcpy_ext(pmpriv->adapter, (t_u8 *)assoc_succ->ssid,
1676 pbss_desc->ssid.ssid, pbss_desc->ssid.ssid_len,
1677 MLAN_MAX_SSID_LENGTH);
1678 assoc_succ->rssi = pbss_desc->rssi;
1679 assoc_succ->channel = pbss_desc->channel;
1680 wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_ASSOC_SUCC_LOGGER, pevent);
1681
1682 done:
1683 /* Need to indicate IOCTL complete */
1684 if (pioctl_req != MNULL) {
1685 if (ret != MLAN_STATUS_SUCCESS) {
1686 if (passoc_rsp->status_code)
1687 pioctl_req->status_code =
1688 (wlan_le16_to_cpu(*(t_u16 *)&passoc_rsp
1689 ->capability)
1690 << 16) +
1691 passoc_rsp->status_code;
1692 else
1693 pioctl_req->status_code =
1694 MLAN_ERROR_CMD_ASSOC_FAIL;
1695 } else {
1696 pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
1697 }
1698 }
1699
1700 LEAVE();
1701 return ret;
1702 }
1703
1704 /**
1705 * @brief This function prepares command of ad_hoc_start.
1706 *
1707 * @param pmpriv A pointer to mlan_private structure
1708 * @param cmd A pointer to HostCmd_DS_COMMAND structure
1709 * @param pdata_buf A pointer cast of mlan_802_11_ssid structure
1710 *
1711 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1712 */
wlan_cmd_802_11_ad_hoc_start(mlan_private * pmpriv,HostCmd_DS_COMMAND * cmd,t_void * pdata_buf)1713 mlan_status wlan_cmd_802_11_ad_hoc_start(mlan_private *pmpriv,
1714 HostCmd_DS_COMMAND *cmd,
1715 t_void *pdata_buf)
1716 {
1717 mlan_status ret = MLAN_STATUS_SUCCESS;
1718 mlan_adapter *pmadapter = pmpriv->adapter;
1719 HostCmd_DS_802_11_AD_HOC_START *padhoc_start = &cmd->params.adhoc_start;
1720 BSSDescriptor_t *pbss_desc;
1721 t_u32 cmd_append_size = 0;
1722 t_u32 i;
1723 t_u16 tmp_cap;
1724 MrvlIEtypes_ChanListParamSet_t *pchan_tlv;
1725
1726 MrvlIEtypes_RsnParamSet_t *prsn_ie_tlv;
1727 /* wpa ie for WPA_NONE AES */
1728 const t_u8 wpa_ie[24] = {0xdd, 0x16, 0x00, 0x50, 0xf2, 0x01,
1729 0x01, 0x00, 0x00, 0x50, 0xf2, 0x04,
1730 0x01, 0x00, 0x00, 0x50, 0xf2, 0x00,
1731 0x01, 0x00, 0x00, 0x50, 0xf2, 0x00};
1732 t_s32 append_size_11h = 0;
1733 t_u8 *pos =
1734 (t_u8 *)padhoc_start + sizeof(HostCmd_DS_802_11_AD_HOC_START);
1735
1736 ENTER();
1737
1738 if (!pmadapter) {
1739 ret = MLAN_STATUS_FAILURE;
1740 goto done;
1741 }
1742
1743 cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_START);
1744
1745 pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
1746 pmpriv->pattempted_bss_desc = pbss_desc;
1747
1748 /*
1749 * Fill in the parameters for 2 data structures:
1750 * 1. HostCmd_DS_802_11_AD_HOC_START command
1751 * 2. pbss_desc
1752 * Driver will fill up SSID, bss_mode,IBSS param, Physical Param,
1753 * probe delay, and Cap info.
1754 * Firmware will fill up beacon period, Basic rates
1755 * and operational rates.
1756 */
1757
1758 memset(pmadapter, padhoc_start->ssid, 0, MLAN_MAX_SSID_LENGTH);
1759
1760 memcpy_ext(pmadapter, padhoc_start->ssid,
1761 ((mlan_802_11_ssid *)pdata_buf)->ssid,
1762 ((mlan_802_11_ssid *)pdata_buf)->ssid_len,
1763 MLAN_MAX_SSID_LENGTH);
1764
1765 PRINTM(MINFO, "ADHOC_S_CMD: SSID = %s\n", padhoc_start->ssid);
1766
1767 memset(pmadapter, pbss_desc->ssid.ssid, 0, MLAN_MAX_SSID_LENGTH);
1768 memcpy_ext(pmadapter, pbss_desc->ssid.ssid,
1769 ((mlan_802_11_ssid *)pdata_buf)->ssid,
1770 ((mlan_802_11_ssid *)pdata_buf)->ssid_len,
1771 MLAN_MAX_SSID_LENGTH);
1772
1773 pbss_desc->ssid.ssid_len =
1774 MIN(MLAN_MAX_SSID_LENGTH,
1775 ((mlan_802_11_ssid *)pdata_buf)->ssid_len);
1776
1777 /* Set the BSS mode */
1778 padhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS;
1779 pbss_desc->bss_mode = MLAN_BSS_MODE_IBSS;
1780 padhoc_start->beacon_period = wlan_cpu_to_le16(pmpriv->beacon_period);
1781 pbss_desc->beacon_period = pmpriv->beacon_period;
1782
1783 /* Set Physical param set */
1784 /** Parameter IE Id */
1785 #define DS_PARA_IE_ID 3
1786 /** Parameter IE length */
1787 #define DS_PARA_IE_LEN 1
1788
1789 padhoc_start->phy_param_set.ds_param_set.element_id = DS_PARA_IE_ID;
1790 padhoc_start->phy_param_set.ds_param_set.len = DS_PARA_IE_LEN;
1791
1792 if (!wlan_get_cfp_by_band_and_channel(
1793 pmadapter, pmadapter->adhoc_start_band,
1794 (t_u16)pmpriv->adhoc_channel, pmadapter->region_channel)) {
1795 chan_freq_power_t *cfp;
1796 cfp = wlan_get_cfp_by_band_and_channel(
1797 pmadapter, pmadapter->adhoc_start_band,
1798 FIRST_VALID_CHANNEL, pmadapter->region_channel);
1799 if (cfp)
1800 pmpriv->adhoc_channel = (t_u8)cfp->channel;
1801 }
1802
1803 MASSERT(pmpriv->adhoc_channel);
1804
1805 PRINTM(MINFO, "ADHOC_S_CMD: Creating ADHOC on Channel %d\n",
1806 pmpriv->adhoc_channel);
1807
1808 pmpriv->curr_bss_params.bss_descriptor.channel = pmpriv->adhoc_channel;
1809 pmpriv->curr_bss_params.band = pmadapter->adhoc_start_band;
1810
1811 pbss_desc->channel = pmpriv->adhoc_channel;
1812 padhoc_start->phy_param_set.ds_param_set.current_chan =
1813 pmpriv->adhoc_channel;
1814
1815 memcpy_ext(pmadapter, &pbss_desc->phy_param_set,
1816 &padhoc_start->phy_param_set,
1817 sizeof(IEEEtypes_PhyParamSet_t),
1818 sizeof(IEEEtypes_PhyParamSet_t));
1819
1820 pbss_desc->network_type_use = Wlan802_11DS;
1821
1822 /* Set IBSS param set */
1823 /** IBSS parameter IE Id */
1824 #define IBSS_PARA_IE_ID 6
1825 /** IBSS parameter IE length */
1826 #define IBSS_PARA_IE_LEN 2
1827
1828 padhoc_start->ss_param_set.ibss_param_set.element_id = IBSS_PARA_IE_ID;
1829 padhoc_start->ss_param_set.ibss_param_set.len = IBSS_PARA_IE_LEN;
1830 padhoc_start->ss_param_set.ibss_param_set.atim_window =
1831 wlan_cpu_to_le16(pmpriv->atim_window);
1832 pbss_desc->atim_window = pmpriv->atim_window;
1833 memcpy_ext(pmadapter, &pbss_desc->ss_param_set,
1834 &padhoc_start->ss_param_set, sizeof(IEEEtypes_SsParamSet_t),
1835 sizeof(IEEEtypes_SsParamSet_t));
1836
1837 /* Set Capability info */
1838 padhoc_start->cap.ess = 0;
1839 padhoc_start->cap.ibss = 1;
1840 pbss_desc->cap_info.ibss = 1;
1841
1842 /* Set up privacy in pbss_desc */
1843 if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled ||
1844 pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.ewpa_enabled) {
1845 /** Ad-Hoc capability privacy on */
1846 #define AD_HOC_CAP_PRIVACY_ON 1
1847 PRINTM(MINFO, "ADHOC_S_CMD: wep_status set, Privacy to WEP\n");
1848 pbss_desc->privacy = Wlan802_11PrivFilter8021xWEP;
1849 padhoc_start->cap.privacy = AD_HOC_CAP_PRIVACY_ON;
1850 } else {
1851 PRINTM(MWARN, "ADHOC_S_CMD: wep_status NOT set, Setting "
1852 "Privacy to ACCEPT ALL\n");
1853 pbss_desc->privacy = Wlan802_11PrivFilterAcceptAll;
1854 }
1855
1856 memset(pmadapter, padhoc_start->DataRate, 0,
1857 sizeof(padhoc_start->DataRate));
1858
1859 if ((pmpriv->adapter->region_code == COUNTRY_CODE_JP_40 ||
1860 pmpriv->adapter->region_code == COUNTRY_CODE_JP_FF) &&
1861 (pbss_desc->phy_param_set.ds_param_set.current_chan == 14)) {
1862 wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode, BAND_B,
1863 padhoc_start->DataRate);
1864 } else {
1865 wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode,
1866 pmadapter->adhoc_start_band,
1867 padhoc_start->DataRate);
1868 }
1869
1870 if ((pmadapter->adhoc_start_band & BAND_G) &&
1871 (pmpriv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) {
1872 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
1873 HostCmd_ACT_GEN_SET, 0, MNULL,
1874 &pmpriv->curr_pkt_filter);
1875
1876 if (ret) {
1877 PRINTM(MERROR,
1878 "ADHOC_S_CMD: G Protection config failed\n");
1879 ret = MLAN_STATUS_FAILURE;
1880 goto done;
1881 }
1882 }
1883 /* Find the last non zero */
1884 for (i = 0;
1885 i < sizeof(padhoc_start->DataRate) && padhoc_start->DataRate[i];
1886 i++)
1887 /* XXX Do not delete no-operation line */
1888 ;
1889
1890 pmpriv->curr_bss_params.num_of_rates = i;
1891
1892 /* Copy the ad-hoc creating rates into Current BSS rate structure */
1893 memcpy_ext(pmadapter, &pmpriv->curr_bss_params.data_rates,
1894 &padhoc_start->DataRate,
1895 pmpriv->curr_bss_params.num_of_rates, WLAN_SUPPORTED_RATES);
1896
1897 PRINTM(MINFO, "ADHOC_S_CMD: Rates=%02x %02x %02x %02x\n",
1898 padhoc_start->DataRate[0], padhoc_start->DataRate[1],
1899 padhoc_start->DataRate[2], padhoc_start->DataRate[3]);
1900
1901 PRINTM(MINFO, "ADHOC_S_CMD: AD HOC Start command is ready\n");
1902
1903 if (IS_SUPPORT_MULTI_BANDS(pmadapter)) {
1904 /* Append a channel TLV */
1905 pchan_tlv = (MrvlIEtypes_ChanListParamSet_t *)pos;
1906 pchan_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
1907 pchan_tlv->header.len =
1908 wlan_cpu_to_le16(sizeof(ChanScanParamSet_t));
1909
1910 memset(pmadapter, pchan_tlv->chan_scan_param, 0x00,
1911 sizeof(ChanScanParamSet_t));
1912 pchan_tlv->chan_scan_param[0].chan_number =
1913 (t_u8)pmpriv->curr_bss_params.bss_descriptor.channel;
1914
1915 PRINTM(MINFO, "ADHOC_S_CMD: TLV Chan = %d\n",
1916 pchan_tlv->chan_scan_param[0].chan_number);
1917
1918 pchan_tlv->chan_scan_param[0].bandcfg.chanBand =
1919 wlan_band_to_radio_type(pmpriv->curr_bss_params.band);
1920 PRINTM(MINFO, "ADHOC_S_CMD: TLV Bandcfg = %x\n",
1921 pchan_tlv->chan_scan_param[0].bandcfg);
1922 pos += sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
1923 cmd_append_size +=
1924 sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
1925 }
1926
1927 if (wlan_11d_create_dnld_countryinfo(pmpriv,
1928 pmpriv->curr_bss_params.band)) {
1929 PRINTM(MERROR, "ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
1930 ret = MLAN_STATUS_FAILURE;
1931 goto done;
1932 }
1933
1934 /*
1935 * Call 11h start API to add any 11h flags/elements as TLV parameters
1936 */
1937 append_size_11h =
1938 wlan_11h_process_start(pmpriv, &pos, &padhoc_start->cap,
1939 pmpriv->adhoc_channel,
1940 &pbss_desc->wlan_11h_bss_info);
1941 if (append_size_11h >= 0)
1942 cmd_append_size += append_size_11h;
1943 else {
1944 ret = MLAN_STATUS_FAILURE;
1945 goto done;
1946 }
1947
1948 if (pmpriv->sec_info.ewpa_enabled) {
1949 memcpy_ext(pmadapter, pmpriv->wpa_ie, wpa_ie, sizeof(wpa_ie),
1950 sizeof(pmpriv->wpa_ie));
1951 pmpriv->wpa_ie_len = sizeof(wpa_ie);
1952 }
1953
1954 if (pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.ewpa_enabled) {
1955 prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
1956 prsn_ie_tlv->header.type = (t_u16)pmpriv->wpa_ie[0];
1957 /* WPA_IE or RSN_IE */
1958 prsn_ie_tlv->header.type = prsn_ie_tlv->header.type & 0x00FF;
1959 prsn_ie_tlv->header.type =
1960 wlan_cpu_to_le16(prsn_ie_tlv->header.type);
1961 prsn_ie_tlv->header.len = (t_u16)pmpriv->wpa_ie[1];
1962 prsn_ie_tlv->header.len = prsn_ie_tlv->header.len & 0x00FF;
1963 if (prsn_ie_tlv->header.len <= (sizeof(pmpriv->wpa_ie) - 2))
1964 memcpy_ext(pmadapter, prsn_ie_tlv->rsn_ie,
1965 &pmpriv->wpa_ie[2], prsn_ie_tlv->header.len,
1966 prsn_ie_tlv->header.len);
1967 else {
1968 ret = MLAN_STATUS_FAILURE;
1969 goto done;
1970 }
1971
1972 DBG_HEXDUMP(MCMD_D, "ADHOC_S_CMD: RSN IE", (t_u8 *)prsn_ie_tlv,
1973 sizeof(prsn_ie_tlv->header) +
1974 prsn_ie_tlv->header.len);
1975 pos += sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len;
1976 cmd_append_size +=
1977 sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len;
1978 prsn_ie_tlv->header.len =
1979 wlan_cpu_to_le16(prsn_ie_tlv->header.len);
1980 }
1981
1982 cmd->size = (t_u16)wlan_cpu_to_le16(
1983 (t_u16)(sizeof(HostCmd_DS_802_11_AD_HOC_START) + S_DS_GEN +
1984 cmd_append_size));
1985
1986 memcpy_ext(pmadapter, &tmp_cap, &padhoc_start->cap, sizeof(t_u16),
1987 sizeof(tmp_cap));
1988
1989 if (pmadapter->adhoc_start_band == BAND_B)
1990 SHORT_SLOT_TIME_DISABLED(tmp_cap);
1991 else
1992 SHORT_SLOT_TIME_ENABLED(tmp_cap);
1993
1994 tmp_cap = wlan_cpu_to_le16(tmp_cap);
1995 memcpy_ext(pmadapter, &padhoc_start->cap, &tmp_cap, sizeof(t_u16),
1996 sizeof(padhoc_start->cap));
1997
1998 ret = MLAN_STATUS_SUCCESS;
1999 done:
2000 LEAVE();
2001 return ret;
2002 }
2003
2004 /**
2005 * @brief This function prepares command of ad_hoc_join.
2006 *
2007 * @param pmpriv A pointer to mlan_private structure
2008 * @param cmd A pointer to HostCmd_DS_COMMAND structure
2009 * @param pdata_buf Void cast of BSSDescriptor_t from the
2010 * scan table to join
2011 *
2012 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2013 */
wlan_cmd_802_11_ad_hoc_join(mlan_private * pmpriv,HostCmd_DS_COMMAND * cmd,t_void * pdata_buf)2014 mlan_status wlan_cmd_802_11_ad_hoc_join(mlan_private *pmpriv,
2015 HostCmd_DS_COMMAND *cmd,
2016 t_void *pdata_buf)
2017 {
2018 mlan_status ret = MLAN_STATUS_SUCCESS;
2019 mlan_adapter *pmadapter = pmpriv->adapter;
2020 HostCmd_DS_802_11_AD_HOC_JOIN *padhoc_join = &cmd->params.adhoc_join;
2021 BSSDescriptor_t *pbss_desc = (BSSDescriptor_t *)pdata_buf;
2022 MrvlIEtypes_ChanListParamSet_t *pchan_tlv;
2023 MrvlIEtypes_RsnParamSet_t *prsn_ie_tlv;
2024 t_u32 cmd_append_size = 0;
2025 t_u16 tmp_cap;
2026 t_u32 i, rates_size = 0;
2027 t_u32 curr_pkt_filter;
2028 t_u8 *pos = (t_u8 *)padhoc_join + sizeof(HostCmd_DS_802_11_AD_HOC_JOIN);
2029 t_s32 append_size_11h = 0;
2030
2031 ENTER();
2032
2033 /** Use G protection */
2034 #define USE_G_PROTECTION 0x02
2035 if (pbss_desc->erp_flags & USE_G_PROTECTION) {
2036 curr_pkt_filter = pmpriv->curr_pkt_filter |
2037 HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON;
2038
2039 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
2040 HostCmd_ACT_GEN_SET, 0, MNULL,
2041 &curr_pkt_filter);
2042 if (ret) {
2043 PRINTM(MERROR,
2044 "ADHOC_J_CMD: G Protection config failed\n");
2045 ret = MLAN_STATUS_FAILURE;
2046 goto done;
2047 }
2048 }
2049
2050 pmpriv->pattempted_bss_desc = pbss_desc;
2051
2052 cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_JOIN);
2053
2054 padhoc_join->bss_descriptor.bss_mode = HostCmd_BSS_MODE_IBSS;
2055
2056 padhoc_join->bss_descriptor.beacon_period =
2057 wlan_cpu_to_le16(pbss_desc->beacon_period);
2058
2059 memcpy_ext(pmadapter, &padhoc_join->bss_descriptor.bssid,
2060 &pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH,
2061 MLAN_MAC_ADDR_LENGTH);
2062
2063 memcpy_ext(pmadapter, &padhoc_join->bss_descriptor.ssid,
2064 &pbss_desc->ssid.ssid, pbss_desc->ssid.ssid_len,
2065 MLAN_MAX_SSID_LENGTH);
2066
2067 memcpy_ext(pmadapter, &padhoc_join->bss_descriptor.phy_param_set,
2068 &pbss_desc->phy_param_set, sizeof(IEEEtypes_PhyParamSet_t),
2069 sizeof(IEEEtypes_PhyParamSet_t));
2070
2071 padhoc_join->bss_descriptor.phy_param_set.fh_param_set.dwell_time =
2072 wlan_cpu_to_le16(padhoc_join->bss_descriptor.phy_param_set
2073 .fh_param_set.dwell_time);
2074
2075 memcpy_ext(pmadapter, &padhoc_join->bss_descriptor.ss_param_set,
2076 &pbss_desc->ss_param_set, sizeof(IEEEtypes_SsParamSet_t),
2077 sizeof(IEEEtypes_SsParamSet_t));
2078 padhoc_join->bss_descriptor.ss_param_set.ibss_param_set.atim_window = 0;
2079 padhoc_join->bss_descriptor.ss_param_set.ibss_param_set.atim_window =
2080 wlan_cpu_to_le16(padhoc_join->bss_descriptor.ss_param_set
2081 .ibss_param_set.atim_window);
2082
2083 memcpy_ext(pmadapter, &tmp_cap, &pbss_desc->cap_info,
2084 sizeof(IEEEtypes_CapInfo_t), sizeof(IEEEtypes_CapInfo_t));
2085
2086 tmp_cap &= CAPINFO_MASK;
2087
2088 PRINTM(MINFO, "ADHOC_J_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n", tmp_cap,
2089 CAPINFO_MASK);
2090 memcpy_ext(pmadapter, &padhoc_join->bss_descriptor.cap, &tmp_cap,
2091 sizeof(IEEEtypes_CapInfo_t), sizeof(IEEEtypes_CapInfo_t));
2092
2093 /* Information on BSSID descriptor passed to FW */
2094 PRINTM(MINFO, "ADHOC_J_CMD: BSSID = " MACSTR ", SSID = %s\n",
2095 MAC2STR(padhoc_join->bss_descriptor.bssid),
2096 padhoc_join->bss_descriptor.ssid);
2097
2098 for (i = 0; i < WLAN_SUPPORTED_RATES && pbss_desc->supported_rates[i];
2099 i++)
2100 /* XXX Do not delete no-operation line */
2101 ;
2102 rates_size = i;
2103
2104 /* Copy Data Rates from the Rates recorded in scan response */
2105 memset(pmadapter, padhoc_join->bss_descriptor.data_rates, 0,
2106 sizeof(padhoc_join->bss_descriptor.data_rates));
2107 memcpy_ext(pmadapter, padhoc_join->bss_descriptor.data_rates,
2108 pbss_desc->supported_rates, rates_size,
2109 WLAN_SUPPORTED_RATES);
2110
2111 HEXDUMP("Adapted Rates:", padhoc_join->bss_descriptor.data_rates,
2112 rates_size);
2113
2114 /* Copy the adhoc join rates into Current BSS state structure */
2115 pmpriv->curr_bss_params.num_of_rates = rates_size;
2116 memcpy_ext(pmadapter, &pmpriv->curr_bss_params.data_rates,
2117 pbss_desc->supported_rates, rates_size,
2118 WLAN_SUPPORTED_RATES);
2119
2120 /* Copy the channel information */
2121 pmpriv->curr_bss_params.bss_descriptor.channel = pbss_desc->channel;
2122 pmpriv->curr_bss_params.band = pbss_desc->bss_band;
2123
2124 if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled ||
2125 pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.ewpa_enabled)
2126 padhoc_join->bss_descriptor.cap.privacy = AD_HOC_CAP_PRIVACY_ON;
2127
2128 if (IS_SUPPORT_MULTI_BANDS(pmadapter)) {
2129 /* Append a channel TLV */
2130 pchan_tlv = (MrvlIEtypes_ChanListParamSet_t *)pos;
2131 pchan_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
2132 pchan_tlv->header.len =
2133 wlan_cpu_to_le16(sizeof(ChanScanParamSet_t));
2134
2135 memset(pmadapter, pchan_tlv->chan_scan_param, 0x00,
2136 sizeof(ChanScanParamSet_t));
2137 pchan_tlv->chan_scan_param[0].chan_number =
2138 (pbss_desc->phy_param_set.ds_param_set.current_chan);
2139 PRINTM(MINFO, "ADHOC_J_CMD: TLV Chan = %d\n",
2140 pchan_tlv->chan_scan_param[0].chan_number);
2141
2142 pchan_tlv->chan_scan_param[0].bandcfg.chanBand =
2143 wlan_band_to_radio_type(pbss_desc->bss_band);
2144
2145 PRINTM(MINFO, "ADHOC_J_CMD: TLV Bandcfg = %x\n",
2146 pchan_tlv->chan_scan_param[0].bandcfg);
2147 pos += sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
2148 cmd_append_size +=
2149 sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
2150 }
2151
2152 if (wlan_11d_create_dnld_countryinfo(pmpriv, pbss_desc->bss_band)) {
2153 PRINTM(MERROR, "Dnld_countryinfo_11d failed\n");
2154 ret = MLAN_STATUS_FAILURE;
2155 goto done;
2156 }
2157 if (wlan_11d_parse_dnld_countryinfo(pmpriv,
2158 pmpriv->pattempted_bss_desc)) {
2159 ret = MLAN_STATUS_FAILURE;
2160 goto done;
2161 }
2162
2163 /*
2164 * Call 11h join API after capability bits are set so
2165 * adhoc/infra 11h behavior can be properly triggered.
2166 * pos modified if data is appended
2167 */
2168 append_size_11h +=
2169 wlan_11h_process_join(pmpriv, &pos,
2170 &padhoc_join->bss_descriptor.cap,
2171 pbss_desc->bss_band, pbss_desc->channel,
2172 &pbss_desc->wlan_11h_bss_info);
2173 if (append_size_11h >= 0)
2174 cmd_append_size += append_size_11h;
2175 else {
2176 ret = MLAN_STATUS_FAILURE;
2177 goto done;
2178 }
2179
2180 if (pmpriv->sec_info.wpa_enabled) {
2181 prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
2182 /* WPA_IE or RSN_IE */
2183 prsn_ie_tlv->header.type = (t_u16)pmpriv->wpa_ie[0];
2184 prsn_ie_tlv->header.type = prsn_ie_tlv->header.type & 0x00FF;
2185 prsn_ie_tlv->header.type =
2186 wlan_cpu_to_le16(prsn_ie_tlv->header.type);
2187 prsn_ie_tlv->header.len = (t_u16)pmpriv->wpa_ie[1];
2188 prsn_ie_tlv->header.len = prsn_ie_tlv->header.len & 0x00FF;
2189 if (prsn_ie_tlv->header.len <= (sizeof(pmpriv->wpa_ie) - 2))
2190 memcpy_ext(pmadapter, prsn_ie_tlv->rsn_ie,
2191 &pmpriv->wpa_ie[2], prsn_ie_tlv->header.len,
2192 prsn_ie_tlv->header.len);
2193 else {
2194 ret = MLAN_STATUS_FAILURE;
2195 goto done;
2196 }
2197
2198 HEXDUMP("ADHOC_JOIN: RSN IE", (t_u8 *)prsn_ie_tlv,
2199 sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len);
2200 pos += sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len;
2201 cmd_append_size +=
2202 sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len;
2203 prsn_ie_tlv->header.len =
2204 wlan_cpu_to_le16(prsn_ie_tlv->header.len);
2205 } else if (pmpriv->sec_info.ewpa_enabled) {
2206 prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
2207 if (pbss_desc->pwpa_ie) {
2208 prsn_ie_tlv->header.type =
2209 (t_u16)(*(pbss_desc->pwpa_ie))
2210 .vend_hdr.element_id;
2211 prsn_ie_tlv->header.type =
2212 prsn_ie_tlv->header.type & 0x00FF;
2213 prsn_ie_tlv->header.type =
2214 wlan_cpu_to_le16(prsn_ie_tlv->header.type);
2215 prsn_ie_tlv->header.len =
2216 (t_u16)(*(pbss_desc->pwpa_ie)).vend_hdr.len;
2217 prsn_ie_tlv->header.len =
2218 prsn_ie_tlv->header.len & 0x00FF;
2219 if (prsn_ie_tlv->header.len <=
2220 (sizeof(pmpriv->wpa_ie))) {
2221 memcpy_ext(pmadapter, prsn_ie_tlv->rsn_ie,
2222 &((*(pbss_desc->pwpa_ie))
2223 .vend_hdr.oui[0]),
2224 prsn_ie_tlv->header.len,
2225 prsn_ie_tlv->header.len);
2226 } else {
2227 ret = MLAN_STATUS_FAILURE;
2228 goto done;
2229 }
2230
2231 HEXDUMP("ADHOC_JOIN: RSN IE", (t_u8 *)prsn_ie_tlv,
2232 sizeof(prsn_ie_tlv->header) +
2233 prsn_ie_tlv->header.len);
2234 pos += sizeof(prsn_ie_tlv->header) +
2235 prsn_ie_tlv->header.len;
2236 cmd_append_size += sizeof(prsn_ie_tlv->header) +
2237 prsn_ie_tlv->header.len;
2238 prsn_ie_tlv->header.len =
2239 wlan_cpu_to_le16(prsn_ie_tlv->header.len);
2240 }
2241 if (pbss_desc->prsn_ie) {
2242 prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
2243 prsn_ie_tlv->header.type =
2244 (t_u16)(*(pbss_desc->prsn_ie))
2245 .ieee_hdr.element_id;
2246 prsn_ie_tlv->header.type =
2247 prsn_ie_tlv->header.type & 0x00FF;
2248 prsn_ie_tlv->header.type =
2249 wlan_cpu_to_le16(prsn_ie_tlv->header.type);
2250 prsn_ie_tlv->header.len =
2251 (t_u16)(*(pbss_desc->prsn_ie)).ieee_hdr.len;
2252 prsn_ie_tlv->header.len =
2253 prsn_ie_tlv->header.len & 0x00FF;
2254 if (prsn_ie_tlv->header.len <=
2255 (sizeof(pmpriv->wpa_ie))) {
2256 memcpy_ext(pmadapter, prsn_ie_tlv->rsn_ie,
2257 &((*(pbss_desc->prsn_ie)).data[0]),
2258 prsn_ie_tlv->header.len,
2259 prsn_ie_tlv->header.len);
2260 } else {
2261 ret = MLAN_STATUS_FAILURE;
2262 goto done;
2263 }
2264
2265 HEXDUMP("ADHOC_JOIN: RSN IE", (t_u8 *)prsn_ie_tlv,
2266 sizeof(prsn_ie_tlv->header) +
2267 prsn_ie_tlv->header.len);
2268 pos += sizeof(prsn_ie_tlv->header) +
2269 prsn_ie_tlv->header.len;
2270 cmd_append_size += sizeof(prsn_ie_tlv->header) +
2271 prsn_ie_tlv->header.len;
2272 prsn_ie_tlv->header.len =
2273 wlan_cpu_to_le16(prsn_ie_tlv->header.len);
2274 }
2275 }
2276
2277 cmd->size = (t_u16)wlan_cpu_to_le16(
2278 (t_u16)(sizeof(HostCmd_DS_802_11_AD_HOC_JOIN) + S_DS_GEN +
2279 cmd_append_size));
2280
2281 memcpy_ext(pmadapter, &tmp_cap, &padhoc_join->bss_descriptor.cap,
2282 sizeof(IEEEtypes_CapInfo_t), sizeof(IEEEtypes_CapInfo_t));
2283 tmp_cap = wlan_cpu_to_le16(tmp_cap);
2284
2285 memcpy_ext(pmadapter, &padhoc_join->bss_descriptor.cap, &tmp_cap,
2286 sizeof(IEEEtypes_CapInfo_t), sizeof(IEEEtypes_CapInfo_t));
2287
2288 done:
2289 LEAVE();
2290 return ret;
2291 }
2292
2293 /**
2294 * @brief This function handles the command response of ad_hoc_start and
2295 * ad_hoc_join
2296 *
2297 * @param pmpriv A pointer to mlan_private structure
2298 * @param resp A pointer to HostCmd_DS_COMMAND
2299 * @param pioctl_buf A pointer to mlan_ioctl_req structure
2300 *
2301 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2302 */
wlan_ret_802_11_ad_hoc(mlan_private * pmpriv,HostCmd_DS_COMMAND * resp,t_void * pioctl_buf)2303 mlan_status wlan_ret_802_11_ad_hoc(mlan_private *pmpriv,
2304 HostCmd_DS_COMMAND *resp, t_void *pioctl_buf)
2305 {
2306 mlan_status ret = MLAN_STATUS_SUCCESS;
2307 mlan_ioctl_req *pioctl_req = (mlan_ioctl_req *)pioctl_buf;
2308 HostCmd_DS_802_11_AD_HOC_START_RESULT *padhoc_start_result =
2309 &resp->params.adhoc_start_result;
2310 HostCmd_DS_802_11_AD_HOC_JOIN_RESULT *padhoc_join_result =
2311 &resp->params.adhoc_join_result;
2312 BSSDescriptor_t *pbss_desc;
2313 t_u16 command = resp->command;
2314 t_u8 result = 0;
2315 t_u8 event_buf[100];
2316 mlan_event *pevent = (mlan_event *)event_buf;
2317 int ie_len = 0;
2318 IEEEtypes_WmmParameter_t *pwmm_param_ie = MNULL;
2319 mlan_adapter *pmadapter = pmpriv->adapter;
2320 const t_u8 wmm_oui[4] = {0x00, 0x50, 0xf2, 0x02};
2321
2322 ENTER();
2323
2324 pmpriv->wmm_enabled = MFALSE;
2325 if (command == HostCmd_CMD_802_11_AD_HOC_START) {
2326 result = padhoc_start_result->result;
2327 ie_len = resp->size -
2328 (sizeof(HostCmd_DS_802_11_AD_HOC_START_RESULT) +
2329 S_DS_GEN);
2330 pwmm_param_ie =
2331 (IEEEtypes_WmmParameter_t
2332 *)((t_u8 *)resp +
2333 (sizeof(HostCmd_DS_802_11_AD_HOC_START_RESULT) +
2334 S_DS_GEN));
2335 } else {
2336 result = padhoc_join_result->result;
2337 ie_len = resp->size -
2338 (sizeof(HostCmd_DS_802_11_AD_HOC_JOIN_RESULT) +
2339 S_DS_GEN);
2340 pwmm_param_ie =
2341 (IEEEtypes_WmmParameter_t
2342 *)((t_u8 *)resp +
2343 (sizeof(HostCmd_DS_802_11_AD_HOC_JOIN_RESULT) +
2344 S_DS_GEN));
2345 }
2346
2347 pbss_desc = pmpriv->pattempted_bss_desc;
2348
2349 /*
2350 * Join result code 0 --> SUCCESS
2351 */
2352 if (result) {
2353 PRINTM(MERROR, "ADHOC_RESP Failed 0x%x\n", result);
2354 if (pmpriv->media_connected == MTRUE)
2355 wlan_reset_connect_state(pmpriv, MTRUE);
2356 if (pmpriv->adhoc_state == ADHOC_STARTING)
2357 pmpriv->adhoc_state = ADHOC_IDLE;
2358
2359 memset(pmpriv->adapter, &pmpriv->curr_bss_params.bss_descriptor,
2360 0x00, sizeof(BSSDescriptor_t));
2361
2362 ret = MLAN_STATUS_FAILURE;
2363 goto done;
2364 }
2365
2366 /* Send a Media Connected event, according to the Spec */
2367 pmpriv->media_connected = MTRUE;
2368
2369 if (command == HostCmd_CMD_802_11_AD_HOC_START) {
2370 PRINTM(MINFO, "ADHOC_S_RESP %s\n", pbss_desc->ssid.ssid);
2371
2372 /* Update the created network descriptor with the new BSSID */
2373 memcpy_ext(pmpriv->adapter, pbss_desc->mac_address,
2374 padhoc_start_result->bssid, MLAN_MAC_ADDR_LENGTH,
2375 MLAN_MAC_ADDR_LENGTH);
2376
2377 pmpriv->adhoc_state = ADHOC_STARTED;
2378 if (pmpriv->adapter->state_rdh.stage == RDH_RESTART_INTFS)
2379 wlan_11h_radar_detected_callback((t_void *)pmpriv);
2380 } else {
2381 /*
2382 * Now the join cmd should be successful.
2383 * If BSSID has changed use SSID to compare instead of BSSID
2384 */
2385 PRINTM(MINFO, "ADHOC_J_RESP %s\n", pbss_desc->ssid.ssid);
2386
2387 /*
2388 * Make a copy of current BSSID descriptor, only needed
2389 * for join since the current descriptor is already
2390 * being used for adhoc start
2391 */
2392 memcpy_ext(pmpriv->adapter,
2393 &pmpriv->curr_bss_params.bss_descriptor, pbss_desc,
2394 sizeof(BSSDescriptor_t), sizeof(BSSDescriptor_t));
2395
2396 pmpriv->adhoc_state = ADHOC_JOINED;
2397 }
2398
2399 /** process wmm ie */
2400 if (ie_len >= (int)sizeof(IEEEtypes_VendorHeader_t)) {
2401 if ((pwmm_param_ie->vend_hdr.element_id ==
2402 VENDOR_SPECIFIC_221) &&
2403 !memcmp(pmadapter, pwmm_param_ie->vend_hdr.oui, wmm_oui,
2404 sizeof(wmm_oui)) &&
2405 (pwmm_param_ie->vend_hdr.len + 2 == ie_len)) {
2406 DBG_HEXDUMP(MCMD_D, "WMM Param", (t_u8 *)pwmm_param_ie,
2407 ie_len);
2408 memcpy_ext(pmpriv->adapter,
2409 (t_u8 *)&pmpriv->curr_bss_params
2410 .bss_descriptor.wmm_ie,
2411 pwmm_param_ie,
2412 (pwmm_param_ie->vend_hdr.len + 2),
2413 sizeof(IEEEtypes_WmmParameter_t));
2414 pmpriv->wmm_enabled = MTRUE;
2415 wlan_wmm_setup_queue_priorities(pmpriv, pwmm_param_ie);
2416 wlan_wmm_setup_ac_downgrade(pmpriv);
2417 }
2418 }
2419 /* Since WMM is not enabled, setup the queues with the defaults */
2420 if (!pmpriv->wmm_enabled)
2421 wlan_wmm_setup_queues(pmpriv);
2422
2423 PRINTM(MINFO, "ADHOC_RESP: Channel = %d\n", pmpriv->adhoc_channel);
2424 PRINTM(MINFO, "ADHOC_RESP: BSSID = " MACSTR "\n",
2425 MAC2STR(pmpriv->curr_bss_params.bss_descriptor.mac_address));
2426
2427 pevent->bss_index = pmpriv->bss_index;
2428 pevent->event_id = MLAN_EVENT_ID_DRV_CONNECTED;
2429 pevent->event_len = MLAN_MAC_ADDR_LENGTH;
2430 memcpy_ext(pmpriv->adapter, (t_u8 *)pevent->event_buf,
2431 (t_u8 *)pmpriv->curr_bss_params.bss_descriptor.mac_address,
2432 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
2433 wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_CONNECTED, pevent);
2434 wlan_save_curr_bcn(pmpriv);
2435
2436 done:
2437 /* Need to indicate IOCTL complete */
2438 if (pioctl_req != MNULL) {
2439 if (ret != MLAN_STATUS_SUCCESS)
2440 pioctl_req->status_code = MLAN_ERROR_CMD_ASSOC_FAIL;
2441 else
2442 pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
2443 }
2444
2445 LEAVE();
2446 return ret;
2447 }
2448
2449 /**
2450 * @brief Associated to a specific BSS discovered in a scan
2451 *
2452 * @param pmpriv A pointer to mlan_private structure
2453 * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
2454 * @param pbss_desc A pointer to the BSS descriptor to associate with.
2455 *
2456 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2457 */
wlan_associate(mlan_private * pmpriv,t_void * pioctl_buf,BSSDescriptor_t * pbss_desc)2458 mlan_status wlan_associate(mlan_private *pmpriv, t_void *pioctl_buf,
2459 BSSDescriptor_t *pbss_desc)
2460 {
2461 mlan_status ret = MLAN_STATUS_SUCCESS;
2462 t_u8 current_bssid[MLAN_MAC_ADDR_LENGTH];
2463 pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
2464
2465 ENTER();
2466
2467 /* Return error if the pmadapter or table entry
2468 * is not marked as infra */
2469 if ((pmpriv->bss_mode != MLAN_BSS_MODE_INFRA) ||
2470 (pbss_desc->bss_mode != MLAN_BSS_MODE_INFRA)) {
2471 if (pioctl_req)
2472 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
2473 LEAVE();
2474 return MLAN_STATUS_FAILURE;
2475 }
2476
2477 memcpy_ext(pmpriv->adapter, ¤t_bssid,
2478 &pmpriv->curr_bss_params.bss_descriptor.mac_address,
2479 sizeof(current_bssid), sizeof(current_bssid));
2480
2481 /* Clear any past association response stored for application retrieval
2482 */
2483 pmpriv->assoc_rsp_size = 0;
2484
2485 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_ASSOCIATE,
2486 HostCmd_ACT_GEN_SET, 0, pioctl_buf, pbss_desc);
2487
2488 LEAVE();
2489 return ret;
2490 }
2491
2492 /**
2493 * @brief Start an Adhoc Network
2494 *
2495 * @param pmpriv A pointer to mlan_private structure
2496 * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
2497 * @param padhoc_ssid The ssid of the Adhoc Network
2498 *
2499 * @return MLAN_STATUS_SUCCESS--success, MLAN_STATUS_FAILURE--fail
2500 */
wlan_adhoc_start(mlan_private * pmpriv,t_void * pioctl_buf,mlan_802_11_ssid * padhoc_ssid)2501 mlan_status wlan_adhoc_start(mlan_private *pmpriv, t_void *pioctl_buf,
2502 mlan_802_11_ssid *padhoc_ssid)
2503 {
2504 mlan_status ret = MLAN_STATUS_SUCCESS;
2505 wlan_meas_state_t *pmeas_state = &pmpriv->adapter->state_meas;
2506 t_u8 radar = MFALSE;
2507 pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
2508
2509 ENTER();
2510
2511 /*
2512 * If the report indicates no measurement was done, leave the default
2513 * return value alone.
2514 */
2515 if (!pmeas_state->meas_rpt_returned.rpt.basic.map.unmeasured) {
2516 radar = pmeas_state->meas_rpt_returned.rpt.basic.map.radar ?
2517 MTRUE :
2518 MFALSE;
2519 }
2520
2521 if (radar) {
2522 if (pioctl_req)
2523 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
2524 ret = MLAN_STATUS_FAILURE;
2525 LEAVE();
2526 return ret;
2527 }
2528
2529 PRINTM(MINFO, "Adhoc Channel = %d\n", pmpriv->adhoc_channel);
2530 PRINTM(MINFO, "curr_bss_params.channel = %d\n",
2531 pmpriv->curr_bss_params.bss_descriptor.channel);
2532 PRINTM(MINFO, "curr_bss_params.band = %d\n",
2533 pmpriv->curr_bss_params.band);
2534
2535 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_AD_HOC_START,
2536 HostCmd_ACT_GEN_SET, 0, pioctl_buf, padhoc_ssid);
2537 #if defined(STA_SUPPORT)
2538 if (ret == MLAN_STATUS_SUCCESS)
2539 memcpy_ext(pmpriv->adapter, &pmpriv->adhoc_last_start_ssid,
2540 padhoc_ssid, sizeof(mlan_802_11_ssid),
2541 sizeof(mlan_802_11_ssid));
2542 #endif
2543
2544 LEAVE();
2545 return ret;
2546 }
2547
2548 /**
2549 * @brief Join an adhoc network found in a previous scan
2550 *
2551 * @param pmpriv A pointer to mlan_private structure
2552 * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
2553 * @param pbss_desc A pointer to the BSS descriptor found in a previous
2554 * scan to attempt to join
2555 *
2556 * @return MLAN_STATUS_SUCCESS--success, MLAN_STATUS_FAILURE--fail
2557 */
wlan_adhoc_join(mlan_private * pmpriv,t_void * pioctl_buf,BSSDescriptor_t * pbss_desc)2558 mlan_status wlan_adhoc_join(mlan_private *pmpriv, t_void *pioctl_buf,
2559 BSSDescriptor_t *pbss_desc)
2560 {
2561 pmlan_adapter pmadapter = pmpriv->adapter;
2562 mlan_status ret = MLAN_STATUS_SUCCESS;
2563 pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
2564
2565 ENTER();
2566
2567 PRINTM(MINFO, "wlan_adhoc_join: CurBss.ssid =%s\n",
2568 pmpriv->curr_bss_params.bss_descriptor.ssid.ssid);
2569 PRINTM(MINFO, "wlan_adhoc_join: CurBss.ssid_len =%u\n",
2570 pmpriv->curr_bss_params.bss_descriptor.ssid.ssid_len);
2571 PRINTM(MINFO, "wlan_adhoc_join: ssid =%s\n", pbss_desc->ssid.ssid);
2572 PRINTM(MINFO, "wlan_adhoc_join: ssid len =%u\n",
2573 pbss_desc->ssid.ssid_len);
2574
2575 /* Check if the requested SSID is already joined */
2576 if (pmpriv->curr_bss_params.bss_descriptor.ssid.ssid_len &&
2577 !wlan_ssid_cmp(pmadapter, &pbss_desc->ssid,
2578 &pmpriv->curr_bss_params.bss_descriptor.ssid) &&
2579 (pmpriv->curr_bss_params.bss_descriptor.bss_mode ==
2580 MLAN_BSS_MODE_IBSS)) {
2581 PRINTM(MINFO,
2582 "ADHOC_J_CMD: New ad-hoc SSID is the same as current, "
2583 "not attempting to re-join\n");
2584
2585 if (pioctl_req)
2586 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
2587 LEAVE();
2588 return MLAN_STATUS_FAILURE;
2589 }
2590
2591 PRINTM(MINFO, "curr_bss_params.channel = %d\n",
2592 pmpriv->curr_bss_params.bss_descriptor.channel);
2593 PRINTM(MINFO, "curr_bss_params.band = %d\n",
2594 pmpriv->curr_bss_params.band);
2595
2596 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_AD_HOC_JOIN,
2597 HostCmd_ACT_GEN_SET, 0, pioctl_buf, pbss_desc);
2598
2599 LEAVE();
2600 return ret;
2601 }
2602
2603 /**
2604 * @brief Send Deauthentication Request or Stop the AdHoc network depending on
2605 * mode
2606 *
2607 * @param pmpriv A pointer to mlan_private structure
2608 * @param pioctl_req A pointer to mlan_ioctl_req structure
2609 * @param deauth_param A pointer to mlan_deauth_param structure
2610 *
2611 * @return MLAN_STATUS_SUCCESS--success, MLAN_STATUS_FAILURE--fail,
2612 * MLAN_STATUS_PENDING--pending
2613 */
wlan_disconnect(mlan_private * pmpriv,mlan_ioctl_req * pioctl_req,mlan_deauth_param * deauth_param)2614 mlan_status wlan_disconnect(mlan_private *pmpriv, mlan_ioctl_req *pioctl_req,
2615 mlan_deauth_param *deauth_param)
2616 {
2617 mlan_status ret = MLAN_STATUS_SUCCESS;
2618 mlan_deauth_param local_param = {.mac_addr = {0, 0, 0, 0, 0, 0},
2619 .reason_code = DEF_DEAUTH_REASON_CODE};
2620 t_u8 zero_mac[] = {0, 0, 0, 0, 0, 0};
2621
2622 ENTER();
2623
2624 if (deauth_param)
2625 memcpy_ext(pmpriv->adapter, &local_param, deauth_param,
2626 sizeof(*deauth_param), sizeof(local_param));
2627 if (pmpriv->media_connected == MTRUE) {
2628 if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) {
2629 if (!deauth_param ||
2630 !memcmp(pmpriv->adapter, deauth_param->mac_addr,
2631 zero_mac, sizeof(zero_mac)))
2632 memcpy_ext(pmpriv->adapter,
2633 local_param.mac_addr,
2634 (t_u8 *)&pmpriv->curr_bss_params
2635 .bss_descriptor.mac_address,
2636 MLAN_MAC_ADDR_LENGTH,
2637 MLAN_MAC_ADDR_LENGTH);
2638 #ifdef WIFI_DIRECT_SUPPORT
2639 if (pmpriv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
2640 ret = wlan_prepare_cmd(
2641 pmpriv, HostCmd_CMD_802_11_DISASSOCIATE,
2642 HostCmd_ACT_GEN_SET, 0,
2643 (t_void *)pioctl_req, &local_param);
2644 else
2645 #endif
2646 ret = wlan_prepare_cmd(
2647 pmpriv,
2648 HostCmd_CMD_802_11_DEAUTHENTICATE,
2649 HostCmd_ACT_GEN_SET, 0,
2650 (t_void *)pioctl_req, &local_param);
2651
2652 if (ret == MLAN_STATUS_SUCCESS && pioctl_req)
2653 ret = MLAN_STATUS_PENDING;
2654
2655 } else if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) {
2656 ret = wlan_prepare_cmd(pmpriv,
2657 HostCmd_CMD_802_11_AD_HOC_STOP,
2658 HostCmd_ACT_GEN_SET, 0,
2659 (t_void *)pioctl_req, MNULL);
2660
2661 if (ret == MLAN_STATUS_SUCCESS && pioctl_req)
2662 ret = MLAN_STATUS_PENDING;
2663 }
2664 }
2665
2666 LEAVE();
2667 return ret;
2668 }
2669
2670 /**
2671 * @brief Convert band to radio type used in channel TLV
2672 *
2673 * @param band Band enumeration to convert to a channel TLV radio type
2674 *
2675 * @return Radio type designator for use in a channel TLV
2676 */
wlan_band_to_radio_type(t_u16 band)2677 t_u8 wlan_band_to_radio_type(t_u16 band)
2678 {
2679 t_u8 ret_radio_type;
2680
2681 ENTER();
2682
2683 switch (band) {
2684 case BAND_A:
2685 case BAND_AN:
2686 case BAND_A | BAND_AN:
2687 case BAND_A | BAND_AN | BAND_AAC:
2688 ret_radio_type = BAND_5GHZ;
2689 break;
2690 case BAND_B:
2691 case BAND_G:
2692 case BAND_B | BAND_G:
2693 default:
2694 ret_radio_type = BAND_2GHZ;
2695 break;
2696 }
2697
2698 LEAVE();
2699 return ret_radio_type;
2700 }
2701