xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlan/mlan_join.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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, &current_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