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