1 /** @file moal_uap_cfg80211.c
2 *
3 * @brief This file contains the functions for uAP CFG80211.
4 *
5 * Copyright (C) 2011-2017, Marvell International Ltd.
6 *
7 * This software file (the "File") is distributed by Marvell International
8 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
9 * (the "License"). You may use, redistribute and/or modify this File in
10 * accordance with the terms and conditions of the License, a copy of which
11 * is available by writing to the Free Software Foundation, Inc.,
12 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
13 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
14 *
15 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
17 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
18 * this warranty disclaimer.
19 *
20 */
21
22 #include "moal_cfg80211.h"
23 #include "moal_uap_cfg80211.h"
24 /** deauth reason code */
25 #define REASON_CODE_DEAUTH_LEAVING 3
26 /********************************************************
27 Local Variables
28 ********************************************************/
29
30 /********************************************************
31 Global Variables
32 ********************************************************/
33 #ifdef WIFI_DIRECT_SUPPORT
34 extern int GoAgeoutTime;
35 #endif
36 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
37 extern int dfs_offload;
38 #endif
39 /********************************************************
40 Local Functions
41 ********************************************************/
42
43 /********************************************************
44 Global Functions
45 ********************************************************/
46 /**
47 * @brief send deauth to station
48 *
49 * @param A pointer to moal_private
50 * @param mac A pointer to station mac address
51 * @param reason_code ieee deauth reason code
52 * @return 0 -- success, otherwise fail
53 */
54 static int
woal_deauth_station(moal_private * priv,u8 * mac_addr,u16 reason_code)55 woal_deauth_station(moal_private *priv, u8 *mac_addr, u16 reason_code)
56 {
57 mlan_ioctl_req *ioctl_req = NULL;
58 mlan_ds_bss *bss = NULL;
59 int ret = 0;
60 mlan_status status = MLAN_STATUS_SUCCESS;
61
62 ENTER();
63
64 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
65 if (ioctl_req == NULL) {
66 ret = -ENOMEM;
67 goto done;
68 }
69 bss = (mlan_ds_bss *)ioctl_req->pbuf;
70 bss->sub_command = MLAN_OID_UAP_DEAUTH_STA;
71 ioctl_req->req_id = MLAN_IOCTL_BSS;
72 ioctl_req->action = MLAN_ACT_SET;
73
74 memcpy(bss->param.deauth_param.mac_addr, mac_addr,
75 MLAN_MAC_ADDR_LENGTH);
76 bss->param.deauth_param.reason_code = reason_code;
77 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
78 if (status != MLAN_STATUS_SUCCESS) {
79 ret = -EFAULT;
80 goto done;
81 }
82
83 done:
84 if (status != MLAN_STATUS_PENDING)
85 kfree(ioctl_req);
86 LEAVE();
87 return ret;
88 }
89
90 /**
91 * @brief send deauth to all station
92 *
93 * @param priv A pointer to moal_private structure
94 *
95 * @return 0 -- success, otherwise fail
96 */
97 static int
woal_deauth_all_station(moal_private * priv)98 woal_deauth_all_station(moal_private *priv)
99 {
100 int ret = -EFAULT;
101 int i = 0;
102 mlan_ds_get_info *info = NULL;
103 mlan_ioctl_req *ioctl_req = NULL;
104 mlan_status status = MLAN_STATUS_SUCCESS;
105
106 ENTER();
107 if (priv->media_connected == MFALSE) {
108 PRINTM(MINFO, "cfg80211: Media not connected!\n");
109 LEAVE();
110 return 0;
111 }
112 PRINTM(MIOCTL, "del all station\n");
113 /* Allocate an IOCTL request buffer */
114 ioctl_req =
115 (mlan_ioctl_req *)
116 woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
117 if (ioctl_req == NULL) {
118 ret = -ENOMEM;
119 goto done;
120 }
121
122 info = (mlan_ds_get_info *)ioctl_req->pbuf;
123 info->sub_command = MLAN_OID_UAP_STA_LIST;
124 ioctl_req->req_id = MLAN_IOCTL_GET_INFO;
125 ioctl_req->action = MLAN_ACT_GET;
126
127 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
128 if (status != MLAN_STATUS_SUCCESS)
129 goto done;
130 if (!info->param.sta_list.sta_count)
131 goto done;
132 for (i = 0; i < info->param.sta_list.sta_count; i++) {
133 PRINTM(MIOCTL, "deauth station " MACSTR "\n",
134 MAC2STR(info->param.sta_list.info[i].mac_address));
135 ret = woal_deauth_station(priv,
136 info->param.sta_list.info[i].
137 mac_address,
138 REASON_CODE_DEAUTH_LEAVING);
139 }
140 woal_sched_timeout(200);
141 done:
142 if (status != MLAN_STATUS_PENDING)
143 kfree(ioctl_req);
144 return ret;
145 }
146
147 /**
148 * @brief Verify RSN IE
149 *
150 * @param rsn_ie Pointer IEEEtypes_Rsn_t structure
151 * @param sys_config Pointer to mlan_uap_bss_param structure
152 *
153 * @return MTRUE/MFALSE
154 */
155 static t_u8
woal_check_rsn_ie(IEEEtypes_Rsn_t * rsn_ie,mlan_uap_bss_param * sys_config)156 woal_check_rsn_ie(IEEEtypes_Rsn_t *rsn_ie, mlan_uap_bss_param *sys_config)
157 {
158 int left = 0;
159 int count = 0;
160 int i = 0;
161 wpa_suite_auth_key_mgmt_t *key_mgmt = NULL;
162 left = rsn_ie->len + 2;
163 if (left < sizeof(IEEEtypes_Rsn_t))
164 return MFALSE;
165 sys_config->wpa_cfg.group_cipher = 0;
166 sys_config->wpa_cfg.pairwise_cipher_wpa2 = 0;
167 sys_config->key_mgmt = 0;
168 /* check the group cipher */
169 switch (rsn_ie->group_cipher.type) {
170 case WPA_CIPHER_TKIP:
171 sys_config->wpa_cfg.group_cipher = CIPHER_TKIP;
172 break;
173 case WPA_CIPHER_AES_CCM:
174 sys_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
175 break;
176 default:
177 break;
178 }
179 count = le16_to_cpu(rsn_ie->pairwise_cipher.count);
180 for (i = 0; i < count; i++) {
181 switch (rsn_ie->pairwise_cipher.list[i].type) {
182 case WPA_CIPHER_TKIP:
183 sys_config->wpa_cfg.pairwise_cipher_wpa2 |= CIPHER_TKIP;
184 break;
185 case WPA_CIPHER_AES_CCM:
186 sys_config->wpa_cfg.pairwise_cipher_wpa2 |=
187 CIPHER_AES_CCMP;
188 break;
189 default:
190 break;
191 }
192 }
193 left -= sizeof(IEEEtypes_Rsn_t) + (count - 1) * sizeof(wpa_suite);
194 if (left < sizeof(wpa_suite_auth_key_mgmt_t))
195 return MFALSE;
196 key_mgmt =
197 (wpa_suite_auth_key_mgmt_t *)((u8 *)rsn_ie +
198 sizeof(IEEEtypes_Rsn_t) + (count -
199 1) *
200 sizeof(wpa_suite));
201 count = le16_to_cpu(key_mgmt->count);
202 if (left <
203 (sizeof(wpa_suite_auth_key_mgmt_t) +
204 (count - 1) * sizeof(wpa_suite)))
205 return MFALSE;
206 for (i = 0; i < count; i++) {
207 switch (key_mgmt->list[i].type) {
208 case RSN_AKM_8021X:
209 sys_config->key_mgmt |= KEY_MGMT_EAP;
210 break;
211 case RSN_AKM_PSK:
212 sys_config->key_mgmt |= KEY_MGMT_PSK;
213 break;
214 case RSN_AKM_PSK_SHA256:
215 sys_config->key_mgmt |= KEY_MGMT_PSK_SHA256;
216 break;
217 }
218 }
219 return MTRUE;
220 }
221
222 /**
223 * @brief Verify WPA IE
224 *
225 * @param wpa_ie Pointer WPA IE
226 * @param sys_config Pointer to mlan_uap_bss_param structure
227 *
228 * @return MTRUE/MFALSE
229 */
230 static t_u8
woal_check_wpa_ie(IEEEtypes_Wpa_t * wpa_ie,mlan_uap_bss_param * sys_config)231 woal_check_wpa_ie(IEEEtypes_Wpa_t *wpa_ie, mlan_uap_bss_param *sys_config)
232 {
233 int left = 0;
234 int count = 0;
235 int i = 0;
236 wpa_suite_auth_key_mgmt_t *key_mgmt = NULL;
237 left = wpa_ie->len + 2;
238 if (left < sizeof(IEEEtypes_Wpa_t))
239 return MFALSE;
240 sys_config->wpa_cfg.group_cipher = 0;
241 sys_config->wpa_cfg.pairwise_cipher_wpa = 0;
242 switch (wpa_ie->group_cipher.type) {
243 case WPA_CIPHER_TKIP:
244 sys_config->wpa_cfg.group_cipher = CIPHER_TKIP;
245 break;
246 case WPA_CIPHER_AES_CCM:
247 sys_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
248 break;
249 default:
250 break;
251 }
252 count = le16_to_cpu(wpa_ie->pairwise_cipher.count);
253 for (i = 0; i < count; i++) {
254 switch (wpa_ie->pairwise_cipher.list[i].type) {
255 case WPA_CIPHER_TKIP:
256 sys_config->wpa_cfg.pairwise_cipher_wpa |= CIPHER_TKIP;
257 break;
258 case WPA_CIPHER_AES_CCM:
259 sys_config->wpa_cfg.pairwise_cipher_wpa |=
260 CIPHER_AES_CCMP;
261 break;
262 default:
263 break;
264 }
265 }
266 left -= sizeof(IEEEtypes_Wpa_t) + (count - 1) * sizeof(wpa_suite);
267 if (left < sizeof(wpa_suite_auth_key_mgmt_t))
268 return MFALSE;
269 key_mgmt =
270 (wpa_suite_auth_key_mgmt_t *)((u8 *)wpa_ie +
271 sizeof(IEEEtypes_Wpa_t) + (count -
272 1) *
273 sizeof(wpa_suite));
274 count = le16_to_cpu(key_mgmt->count);
275 if (left <
276 (sizeof(wpa_suite_auth_key_mgmt_t) +
277 (count - 1) * sizeof(wpa_suite)))
278 return MFALSE;
279 for (i = 0; i < count; i++) {
280 switch (key_mgmt->list[i].type) {
281 case RSN_AKM_8021X:
282 sys_config->key_mgmt = KEY_MGMT_EAP;
283 break;
284 case RSN_AKM_PSK:
285 sys_config->key_mgmt = KEY_MGMT_PSK;
286 break;
287 }
288 }
289 return MTRUE;
290 }
291
292 /**
293 * @brief Find RSN/WPA IES
294 *
295 * @param ie Pointer IE buffer
296 * @param sys_config Pointer to mlan_uap_bss_param structure
297 *
298 * @return MTRUE/MFALSE
299 */
300 static t_u8
woal_find_wpa_ies(const t_u8 * ie,int len,mlan_uap_bss_param * sys_config)301 woal_find_wpa_ies(const t_u8 *ie, int len, mlan_uap_bss_param *sys_config)
302 {
303 int bytes_left = len;
304 const t_u8 *pcurrent_ptr = ie;
305 t_u16 total_ie_len;
306 t_u8 element_len;
307 t_u8 wpa2 = 0;
308 t_u8 wpa = 0;
309 t_u8 ret = MFALSE;
310 IEEEtypes_ElementId_e element_id;
311 IEEEtypes_VendorSpecific_t *pvendor_ie;
312 const t_u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
313
314 while (bytes_left >= 2) {
315 element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
316 element_len = *((t_u8 *)pcurrent_ptr + 1);
317 total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
318 if (bytes_left < total_ie_len) {
319 PRINTM(MERROR,
320 "InterpretIE: Error in processing IE, bytes left < IE length\n");
321 bytes_left = 0;
322 continue;
323 }
324 switch (element_id) {
325 case RSN_IE:
326 wpa2 = woal_check_rsn_ie((IEEEtypes_Rsn_t *)
327 pcurrent_ptr, sys_config);
328 break;
329 case VENDOR_SPECIFIC_221:
330 pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
331 if (!memcmp
332 (pvendor_ie->vend_hdr.oui, wpa_oui,
333 sizeof(pvendor_ie->vend_hdr.oui)) &&
334 (pvendor_ie->vend_hdr.oui_type == wpa_oui[3])) {
335 wpa = woal_check_wpa_ie((IEEEtypes_Wpa_t *)
336 pcurrent_ptr,
337 sys_config);
338 }
339 break;
340 default:
341 break;
342 }
343 pcurrent_ptr += element_len + 2;
344 /* Need to account for IE ID and IE Len */
345 bytes_left -= (element_len + 2);
346 }
347 if (wpa && wpa2) {
348 sys_config->protocol = PROTOCOL_WPA | PROTOCOL_WPA2;
349 ret = MTRUE;
350 } else if (wpa2) {
351 sys_config->protocol = PROTOCOL_WPA2;
352 ret = MTRUE;
353 } else if (wpa) {
354 sys_config->protocol = PROTOCOL_WPA;
355 ret = MTRUE;
356 }
357 return ret;
358 }
359
360 /**
361 * @brief Find and set WMM IES
362 *
363 * @param ie Pointer IE buffer
364 * @param sys_config Pointer to mlan_uap_bss_param structure
365 *
366 * @return N/A
367 */
368 static t_void
woal_set_wmm_ies(const t_u8 * ie,int len,mlan_uap_bss_param * sys_config)369 woal_set_wmm_ies(const t_u8 *ie, int len, mlan_uap_bss_param *sys_config)
370 {
371 int bytes_left = len;
372 const t_u8 *pcurrent_ptr = ie;
373 t_u16 total_ie_len;
374 t_u8 element_len;
375 IEEEtypes_VendorSpecific_t *pvendor_ie;
376 IEEEtypes_ElementId_e element_id;
377 const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
378 t_u8 *poui;
379
380 while (bytes_left >= 2) {
381 element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
382 element_len = *((t_u8 *)pcurrent_ptr + 1);
383 total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
384 if (bytes_left < total_ie_len) {
385 PRINTM(MERROR,
386 "InterpretIE: Error in processing IE, bytes left < IE length\n");
387 bytes_left = 0;
388 continue;
389 }
390 switch (element_id) {
391 case VENDOR_SPECIFIC_221:
392 pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
393 poui = pvendor_ie->vend_hdr.oui;
394 if (!memcmp(poui, wmm_oui, sizeof(wmm_oui))) {
395 if (total_ie_len ==
396 sizeof(IEEEtypes_WmmParameter_t)) {
397 /*
398 * Only accept and copy the WMM IE if
399 * it matches the size expected for the
400 * WMM Parameter IE.
401 */
402 memcpy(&sys_config->wmm_para,
403 pcurrent_ptr +
404 sizeof(IEEEtypes_Header_t),
405 element_len);
406 }
407 }
408
409 break;
410 default:
411 break;
412 }
413 pcurrent_ptr += element_len + 2;
414 /* Need to account for IE ID and IE Len */
415 bytes_left -= (element_len + 2);
416 }
417
418 }
419
420 /**
421 * @brief get ht_cap from beacon ie
422 *
423 * @param ie Pointer to IEs
424 * @param len Total length of ie
425 *
426 * @return ht_cap
427 */
428 static t_u16
woal_get_htcap_info(const t_u8 * ie,int len)429 woal_get_htcap_info(const t_u8 *ie, int len)
430 {
431 t_u16 ht_cap_info = 0;
432 IEEEtypes_HTCap_t *htcap_ie = NULL;
433 htcap_ie =
434 (IEEEtypes_HTCap_t *)woal_parse_ie_tlv(ie, len, HT_CAPABILITY);
435 if (htcap_ie) {
436 /* hostap has converted ht_cap_info to little endian, here conver to host endian */
437 ht_cap_info = woal_le16_to_cpu(htcap_ie->ht_cap.ht_cap_info);
438 PRINTM(MMSG, "Get ht_cap from beacon ies: 0x%x\n", ht_cap_info);
439 }
440 return ht_cap_info;
441 }
442
443 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
444 /** Starting Frequency for 11A band */
445 #define START_FREQ_11A_BAND 5000 /* in MHz */
446 /**
447 * @brief convert cfg80211_chan_def to Band_Config
448 *
449 * @param bandcfg A pointer to (Band_Config_t structure
450 * @param chandef A pointer to cfg80211_chan_def structure
451 *
452 * @return N/A
453 */
454 static void
woal_convert_chan_to_bandconfig(Band_Config_t * bandcfg,struct cfg80211_chan_def * chandef)455 woal_convert_chan_to_bandconfig(Band_Config_t *bandcfg,
456 struct cfg80211_chan_def *chandef)
457 {
458 ENTER();
459 if (chandef->chan->hw_value <= MAX_BG_CHANNEL)
460 bandcfg->chanBand = BAND_2GHZ;
461 else
462 bandcfg->chanBand = BAND_5GHZ;
463 switch (chandef->width) {
464 case NL80211_CHAN_WIDTH_20_NOHT:
465 case NL80211_CHAN_WIDTH_20:
466 bandcfg->chanWidth = CHAN_BW_20MHZ;
467 break;
468 case NL80211_CHAN_WIDTH_40:
469 bandcfg->chanWidth = CHAN_BW_40MHZ;
470 if (chandef->center_freq1 > chandef->chan->center_freq)
471 bandcfg->chan2Offset = SEC_CHAN_ABOVE;
472 else
473 bandcfg->chan2Offset = SEC_CHAN_BELOW;
474 break;
475 default:
476 break;
477 }
478 LEAVE();
479 return;
480 }
481
482 /**
483 * @brief Enable radar detect for DFS channel
484 *
485 * @param priv A pointer to moal private structure
486 * @param chandef A pointer to cfg80211_chan_def structure
487 * @return N/A
488 */
489 static void
woal_enable_dfs_support(moal_private * priv,struct cfg80211_chan_def * chandef)490 woal_enable_dfs_support(moal_private *priv, struct cfg80211_chan_def *chandef)
491 {
492 mlan_ioctl_req *req = NULL;
493 mlan_ds_11h_chan_rep_req *pchan_rpt_req = NULL;
494 mlan_ds_11h_cfg *p11h_cfg = NULL;
495 mlan_status status = MLAN_STATUS_SUCCESS;
496 ENTER();
497 if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) {
498 PRINTM(MIOCTL, "No radar channel\n");
499 LEAVE();
500 return;
501 }
502 PRINTM(MIOCTL, "start Radar detect, chan %d , Bw %d \n",
503 chandef->chan->hw_value, chandef->width);
504
505 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
506 if (NULL == req) {
507 PRINTM(MIOCTL, "No Memory to allocate ioctl buffer\n");
508 LEAVE();
509 return;
510 }
511 p11h_cfg = (mlan_ds_11h_cfg *)req->pbuf;
512 pchan_rpt_req = &p11h_cfg->param.chan_rpt_req;
513 pchan_rpt_req->startFreq = 5000;
514 pchan_rpt_req->chanNum = (t_u8)chandef->chan->hw_value;
515 woal_convert_chan_to_bandconfig(&pchan_rpt_req->bandcfg, chandef);
516 pchan_rpt_req->host_based = MTRUE;
517 pchan_rpt_req->millisec_dwell_time = 0;
518
519 p11h_cfg->sub_command = MLAN_OID_11H_CHANNEL_CHECK;
520 req->req_id = MLAN_IOCTL_11H_CFG;
521 req->action = MLAN_ACT_SET;
522 /* Send Channel Check command and wait until the report is ready */
523 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
524 if (status != MLAN_STATUS_PENDING)
525 kfree(req);
526 LEAVE();
527 return;
528 }
529 #endif
530
531 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
532 /**
533 * @brief initialize AP or GO bss config
534 *
535 * @param priv A pointer to moal private structure
536 * @param params A pointer to cfg80211_ap_settings structure
537 * @return 0 -- success, otherwise fail
538 */
539 static int
woal_cfg80211_beacon_config(moal_private * priv,struct cfg80211_ap_settings * params)540 woal_cfg80211_beacon_config(moal_private *priv,
541 struct cfg80211_ap_settings *params)
542 #else
543 /**
544 * @brief initialize AP or GO bss config
545 *
546 * @param priv A pointer to moal private structure
547 * @param params A pointer to beacon_parameters structure
548 * @return 0 -- success, otherwise fail
549 */
550 static int
551 woal_cfg80211_beacon_config(moal_private *priv,
552 struct beacon_parameters *params)
553 #endif
554 {
555 struct wiphy *wiphy = NULL;
556 const t_u8 *ie = NULL;
557 int ret = 0, ie_len;
558 mlan_uap_bss_param *sys_config = NULL;
559 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
560 int i = 0;
561 #else
562 t_u8 wpa_ies;
563 const t_u8 *ssid_ie = NULL;
564 struct ieee80211_mgmt *head = NULL;
565 t_u16 capab_info = 0;
566 #endif
567 t_u8 rates_bg[13] = {
568 0x82, 0x84, 0x8b, 0x96,
569 0x0c, 0x12, 0x18, 0x24,
570 0x30, 0x48, 0x60, 0x6c,
571 0x00
572 };
573 t_u8 rates_a[9] = {
574 0x8c, 0x12, 0x98, 0x24,
575 0xb0, 0x48, 0x60, 0x6c,
576 0x00
577 };
578 #ifdef WIFI_DIRECT_SUPPORT
579 t_u8 rates_wfd[9] = {
580 0x8c, 0x12, 0x18, 0x24,
581 0x30, 0x48, 0x60, 0x6c,
582 0x00
583 };
584 #endif
585 t_u8 chan2Offset = SEC_CHAN_NONE;
586 t_u8 enable_11n = MTRUE;
587 t_u16 ht_cap = 0;
588 t_u8 *wapi_ie = NULL;
589 int wapi_ie_len = 0;
590 #if defined(DFS_TESTING_SUPPORT)
591 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
592 mlan_ds_11h_chan_nop_info chan_nop_info;
593 Band_Config_t bandcfg;
594 #endif
595 #endif
596 ENTER();
597
598 if (!params) {
599 ret = -EFAULT;
600 goto done;
601 }
602 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
603 ie = ((struct cfg80211_ap_settings *)params)->beacon.tail;
604 ie_len = ((struct cfg80211_ap_settings *)params)->beacon.tail_len;
605 #else
606 ie = ((struct beacon_parameters *)params)->tail;
607 ie_len = ((struct beacon_parameters *)params)->tail_len;
608 #endif
609 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
610 wapi_ie = (t_u8 *)woal_parse_ie_tlv(params->beacon.tail,
611 params->beacon.tail_len, WAPI_IE);
612 #else
613 wapi_ie = (t_u8 *)woal_parse_ie_tlv(params->tail,
614 params->tail_len, WAPI_IE);
615 #endif
616 if (wapi_ie) {
617 wapi_ie_len = *(wapi_ie + 1) + 2;
618 woal_set_get_gen_ie(priv, MLAN_ACT_SET, wapi_ie, &wapi_ie_len,
619 MOAL_IOCTL_WAIT);
620 }
621 wiphy = priv->phandle->wiphy;
622 if (priv->bss_type != MLAN_BSS_TYPE_UAP
623 #ifdef WIFI_DIRECT_SUPPORT
624 && priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT
625 #endif
626 ) {
627 ret = -EFAULT;
628 goto done;
629 }
630 sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
631 if (!sys_config) {
632 PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
633 ret = -EFAULT;
634 goto done;
635 }
636
637 /* Initialize the uap bss values which are uploaded from firmware */
638 if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv,
639 MLAN_ACT_GET,
640 MOAL_IOCTL_WAIT,
641 sys_config)) {
642 PRINTM(MERROR, "Error getting AP confiruration\n");
643 ret = -EFAULT;
644 goto done;
645 }
646
647 /* Setting the default values */
648 sys_config->channel = 6;
649 sys_config->preamble_type = 0;
650 sys_config->mgmt_ie_passthru_mask = priv->mgmt_subtype_mask;
651 memcpy(sys_config->mac_addr, priv->current_addr, ETH_ALEN);
652
653 #ifdef WIFI_DIRECT_SUPPORT
654 if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT && GoAgeoutTime) {
655 sys_config->sta_ageout_timer = GoAgeoutTime;
656 sys_config->ps_sta_ageout_timer = GoAgeoutTime;
657 }
658 #endif
659 /* Set frag_threshold, rts_threshold, and retry limit */
660 sys_config->frag_threshold = wiphy->frag_threshold;
661 sys_config->rts_threshold = wiphy->rts_threshold;
662 sys_config->retry_limit = wiphy->retry_long;
663 if (sys_config->frag_threshold == MLAN_FRAG_RTS_DISABLED) {
664 sys_config->frag_threshold = MLAN_FRAG_MAX_VALUE;
665 }
666 if (sys_config->rts_threshold == MLAN_FRAG_RTS_DISABLED) {
667 sys_config->rts_threshold = MLAN_RTS_MAX_VALUE;
668 }
669
670 if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
671 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
672 if (params->beacon_interval)
673 sys_config->beacon_period = params->beacon_interval;
674 #else
675 if (params->interval)
676 sys_config->beacon_period = params->interval;
677 #endif
678 if (params->dtim_period)
679 sys_config->dtim_period = params->dtim_period;
680 }
681 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
682 /** back up ap's channel */
683 memcpy(&priv->chan, ¶ms->chandef, sizeof(struct cfg80211_chan_def));
684 #endif
685
686 #if defined(DFS_TESTING_SUPPORT)
687 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
688 PRINTM(MCMND, "Checking if AP's channel %d is under NOP\n",
689 priv->channel);
690 woal_convert_chan_to_bandconfig(&bandcfg, ¶ms->chandef);
691 memset(&chan_nop_info, 0, sizeof(chan_nop_info));
692 chan_nop_info.curr_chan = priv->channel;
693 chan_nop_info.chan_width = bandcfg.chanWidth;
694 if (params->chandef.width >= NL80211_CHAN_WIDTH_20)
695 chan_nop_info.new_chan.is_11n_enabled = MTRUE;
696 chan_nop_info.new_chan.bandcfg = bandcfg;
697 woal_uap_get_channel_nop_info(priv, MOAL_IOCTL_WAIT, &chan_nop_info);
698 if (chan_nop_info.chan_under_nop) {
699 PRINTM(MCMND,
700 "cfg80211: Channel %d is under NOP, New channel=%d\n",
701 priv->channel, chan_nop_info.new_chan.channel);
702 priv->chan_under_nop = chan_nop_info.chan_under_nop;
703 priv->channel = chan_nop_info.new_chan.channel;
704 woal_chandef_create(priv, &priv->chan, &chan_nop_info.new_chan);
705 }
706 #endif
707 #endif
708
709 if (priv->channel) {
710 memset(sys_config->rates, 0, sizeof(sys_config->rates));
711 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
712 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
713 switch (priv->chan.width) {
714 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
715 case NL80211_CHAN_WIDTH_5:
716 case NL80211_CHAN_WIDTH_10:
717 #endif
718 case NL80211_CHAN_WIDTH_20_NOHT:
719 enable_11n = MFALSE;
720 break;
721 case NL80211_CHAN_WIDTH_20:
722 break;
723 case NL80211_CHAN_WIDTH_40:
724 if (priv->chan.center_freq1 <
725 priv->chan.chan->center_freq)
726 chan2Offset = SEC_CHAN_BELOW;
727 else
728 chan2Offset = SEC_CHAN_ABOVE;
729 break;
730 case NL80211_CHAN_WIDTH_80:
731 case NL80211_CHAN_WIDTH_80P80:
732 case NL80211_CHAN_WIDTH_160:
733 chan2Offset =
734 woal_get_second_channel_offset(priv->channel);
735 break;
736 default:
737 PRINTM(MWARN, "Unknown channel width: %d\n",
738 priv->chan.width);
739 break;
740 }
741 #else
742 switch (params->channel_type) {
743 case NL80211_CHAN_NO_HT:
744 enable_11n = MFALSE;
745 break;
746 case NL80211_CHAN_HT20:
747 break;
748 case NL80211_CHAN_HT40PLUS:
749 chan2Offset = SEC_CHAN_ABOVE;
750 break;
751 case NL80211_CHAN_HT40MINUS:
752 chan2Offset = SEC_CHAN_BELOW;
753 break;
754 default:
755 PRINTM(MWARN, "Unknown channel type: %d\n",
756 params->channel_type);
757 break;
758 }
759 #endif
760 #endif /* CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
761 sys_config->channel = priv->channel;
762 if (priv->channel <= MAX_BG_CHANNEL) {
763 sys_config->bandcfg.chanBand = BAND_2GHZ;
764 #ifdef WIFI_DIRECT_SUPPORT
765 if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
766 memcpy(sys_config->rates, rates_wfd,
767 sizeof(rates_wfd));
768 else
769 #endif
770 memcpy(sys_config->rates, rates_bg,
771 sizeof(rates_bg));
772 } else {
773 sys_config->bandcfg.chanBand = BAND_5GHZ;
774 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
775 chan2Offset =
776 woal_get_second_channel_offset(priv->channel);
777 #endif
778
779 #ifdef WIFI_DIRECT_SUPPORT
780 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
781
782 /* Force enable 40MHZ on WFD interface */
783 if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
784 chan2Offset =
785 woal_get_second_channel_offset(priv->
786 channel);
787 #endif
788 #endif
789
790 #ifdef WIFI_DIRECT_SUPPORT
791 if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
792 memcpy(sys_config->rates, rates_wfd,
793 sizeof(rates_wfd));
794 else
795 #endif
796 memcpy(sys_config->rates, rates_a,
797 sizeof(rates_a));
798 }
799 /* Disable GreenField by default */
800 sys_config->ht_cap_info = 0x10c;
801 if (enable_11n)
802 sys_config->ht_cap_info |= 0x20;
803 if (chan2Offset) {
804 sys_config->bandcfg.chan2Offset = chan2Offset;
805 sys_config->ht_cap_info |= 0x1042;
806 sys_config->ampdu_param = 3;
807 } else {
808 sys_config->bandcfg.chan2Offset = 0;
809 }
810 if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
811 ht_cap = woal_get_htcap_info(ie, ie_len);
812 if (ht_cap)
813 sys_config->ht_cap_info =
814 (ht_cap &
815 (wiphy->bands[IEEE80211_BAND_2GHZ]->
816 ht_cap.cap & 0x13ff)) | 0x0c;
817 PRINTM(MCMND,
818 "11n=%d, ht_cap=0x%x, channel=%d, bandcfg:chanBand=0x%x chanWidth=0x%x chan2Offset=0x%x scanMode=0x%x\n",
819 enable_11n, sys_config->ht_cap_info,
820 priv->channel, sys_config->bandcfg.chanBand,
821 sys_config->bandcfg.chanWidth,
822 sys_config->bandcfg.chan2Offset,
823 sys_config->bandcfg.scanMode);
824 }
825 }
826 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
827 if (!params->ssid || !params->ssid_len) {
828 ret = -EINVAL;
829 goto done;
830 }
831 memcpy(sys_config->ssid.ssid, params->ssid,
832 MIN(MLAN_MAX_SSID_LENGTH, params->ssid_len));
833 sys_config->ssid.ssid_len = MIN(MLAN_MAX_SSID_LENGTH, params->ssid_len);
834 /**
835 * hidden_ssid=0: broadcast SSID in beacons.
836 * hidden_ssid=1: send empty SSID (length=0) in beacon.
837 * hidden_ssid=2: clear SSID (ACSII 0), but keep the original length
838 */
839 if (!params->hidden_ssid)
840 sys_config->bcast_ssid_ctl = 1;
841 else if (params->hidden_ssid == 1)
842 sys_config->bcast_ssid_ctl = 0;
843 else if (params->hidden_ssid == 2)
844 sys_config->bcast_ssid_ctl = 2;
845 switch (params->auth_type) {
846 case NL80211_AUTHTYPE_SHARED_KEY:
847 sys_config->auth_mode = MLAN_AUTH_MODE_SHARED;
848 break;
849 case NL80211_AUTHTYPE_AUTOMATIC:
850 sys_config->auth_mode = MLAN_AUTH_MODE_AUTO;
851 break;
852 case NL80211_AUTHTYPE_OPEN_SYSTEM:
853 default:
854 sys_config->auth_mode = MLAN_AUTH_MODE_OPEN;
855 break;
856 }
857
858 sys_config->protocol = PROTOCOL_NO_SECURITY;
859 if (params->crypto.n_akm_suites)
860 woal_find_wpa_ies(ie, ie_len, sys_config);
861 for (i = 0; i < params->crypto.n_akm_suites; i++) {
862 switch (params->crypto.akm_suites[i]) {
863 case WLAN_AKM_SUITE_8021X:
864 sys_config->key_mgmt |= KEY_MGMT_EAP;
865 if ((params->crypto.
866 wpa_versions & NL80211_WPA_VERSION_1) &&
867 (params->crypto.
868 wpa_versions & NL80211_WPA_VERSION_2))
869 sys_config->protocol =
870 PROTOCOL_WPA | PROTOCOL_WPA2;
871 else if (params->crypto.
872 wpa_versions & NL80211_WPA_VERSION_2)
873 sys_config->protocol = PROTOCOL_WPA2;
874 else if (params->crypto.
875 wpa_versions & NL80211_WPA_VERSION_1)
876 sys_config->protocol = PROTOCOL_WPA;
877 break;
878 case WLAN_AKM_SUITE_PSK:
879 sys_config->key_mgmt |= KEY_MGMT_PSK;
880 if ((params->crypto.
881 wpa_versions & NL80211_WPA_VERSION_1) &&
882 (params->crypto.
883 wpa_versions & NL80211_WPA_VERSION_2))
884 sys_config->protocol =
885 PROTOCOL_WPA | PROTOCOL_WPA2;
886 else if (params->crypto.
887 wpa_versions & NL80211_WPA_VERSION_2)
888 sys_config->protocol = PROTOCOL_WPA2;
889 else if (params->crypto.
890 wpa_versions & NL80211_WPA_VERSION_1)
891 sys_config->protocol = PROTOCOL_WPA;
892 break;
893 }
894 }
895 sys_config->wpa_cfg.pairwise_cipher_wpa = 0;
896 sys_config->wpa_cfg.pairwise_cipher_wpa2 = 0;
897 for (i = 0; i < params->crypto.n_ciphers_pairwise; i++) {
898 switch (params->crypto.ciphers_pairwise[i]) {
899 case WLAN_CIPHER_SUITE_WEP40:
900 case WLAN_CIPHER_SUITE_WEP104:
901 break;
902 case WLAN_CIPHER_SUITE_TKIP:
903 if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
904 sys_config->wpa_cfg.pairwise_cipher_wpa |=
905 CIPHER_TKIP;
906 if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
907 sys_config->wpa_cfg.pairwise_cipher_wpa2 |=
908 CIPHER_TKIP;
909 break;
910 case WLAN_CIPHER_SUITE_CCMP:
911 if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
912 sys_config->wpa_cfg.pairwise_cipher_wpa |=
913 CIPHER_AES_CCMP;
914 if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
915 sys_config->wpa_cfg.pairwise_cipher_wpa2 |=
916 CIPHER_AES_CCMP;
917 break;
918 case WLAN_CIPHER_SUITE_SMS4:
919 sys_config->protocol = PROTOCOL_WAPI;
920 break;
921 }
922 }
923 switch (params->crypto.cipher_group) {
924 case WLAN_CIPHER_SUITE_WEP40:
925 case WLAN_CIPHER_SUITE_WEP104:
926 if ((priv->cipher == WLAN_CIPHER_SUITE_WEP40) ||
927 (priv->cipher == WLAN_CIPHER_SUITE_WEP104)) {
928 sys_config->protocol = PROTOCOL_STATIC_WEP;
929 sys_config->key_mgmt = KEY_MGMT_NONE;
930 sys_config->wpa_cfg.length = 0;
931 memcpy(&sys_config->wep_cfg.key0, &priv->uap_wep_key[0],
932 sizeof(wep_key));
933 memcpy(&sys_config->wep_cfg.key1, &priv->uap_wep_key[1],
934 sizeof(wep_key));
935 memcpy(&sys_config->wep_cfg.key2, &priv->uap_wep_key[2],
936 sizeof(wep_key));
937 memcpy(&sys_config->wep_cfg.key3, &priv->uap_wep_key[3],
938 sizeof(wep_key));
939 }
940 break;
941 case WLAN_CIPHER_SUITE_TKIP:
942 sys_config->wpa_cfg.group_cipher = CIPHER_TKIP;
943 break;
944 case WLAN_CIPHER_SUITE_CCMP:
945 sys_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
946 break;
947 case WLAN_CIPHER_SUITE_SMS4:
948 sys_config->protocol = PROTOCOL_WAPI;
949 break;
950 }
951 #else
952 /* Since in Android ICS 4.0.1's wpa_supplicant, there is no way to set ssid
953 * when GO (AP) starts up, so get it from beacon head parameter
954 * TODO: right now use hard code
955 * 24 -- ieee80211 header lenth, 12 -- fixed element length for beacon
956 */
957 #define BEACON_IE_OFFSET 36
958 /* Find SSID in head
959 * SSID IE id: 0, right now use hard code
960 */
961 ssid_ie = woal_parse_ie_tlv(params->head + BEACON_IE_OFFSET,
962 params->head_len - BEACON_IE_OFFSET, 0);
963
964 if (!ssid_ie) {
965 PRINTM(MERROR, "No ssid IE found.\n");
966 ret = -EFAULT;
967 goto done;
968 }
969 if (*(ssid_ie + 1) > 32) {
970 PRINTM(MERROR, "ssid len error: %d\n", *(ssid_ie + 1));
971 ret = -EFAULT;
972 goto done;
973 }
974 memcpy(sys_config->ssid.ssid, ssid_ie + 2, *(ssid_ie + 1));
975 sys_config->ssid.ssid_len = *(ssid_ie + 1);
976 head = (struct ieee80211_mgmt *)params->head;
977
978 capab_info = le16_to_cpu(head->u.beacon.capab_info);
979 PRINTM(MIOCTL, "capab_info=0x%x\n", head->u.beacon.capab_info);
980 sys_config->auth_mode = MLAN_AUTH_MODE_OPEN;
981 /** For ICS, we don't support OPEN mode */
982 if ((priv->cipher == WLAN_CIPHER_SUITE_WEP40) ||
983 (priv->cipher == WLAN_CIPHER_SUITE_WEP104)) {
984 sys_config->protocol = PROTOCOL_STATIC_WEP;
985 sys_config->key_mgmt = KEY_MGMT_NONE;
986 sys_config->.wpa_cfg.length = 0;
987 memcpy(&sys_config->wep_cfg.key0, &priv->uap_wep_key[0],
988 sizeof(wep_key));
989 memcpy(&sys_config->wep_cfg.key1, &priv->uap_wep_key[1],
990 sizeof(wep_key));
991 memcpy(&sys_config->wep_cfg.key2, &priv->uap_wep_key[2],
992 sizeof(wep_key));
993 memcpy(&sys_config->wep_cfg.key3, &priv->uap_wep_key[3],
994 sizeof(wep_key));
995 } else {
996 /** Get cipher and key_mgmt from RSN/WPA IE */
997 if (capab_info & WLAN_CAPABILITY_PRIVACY) {
998 wpa_ies =
999 woal_find_wpa_ies(params->tail,
1000 params->tail_len, sys_config);
1001 if (wpa_ies == MFALSE) {
1002 /* hard code setting to wpa2-psk */
1003 sys_config->protocol = PROTOCOL_WPA2;
1004 sys_config->key_mgmt = KEY_MGMT_PSK;
1005 sys_config->wpa_cfg.pairwise_cipher_wpa2 =
1006 CIPHER_AES_CCMP;
1007 sys_config->wpa_cfg.group_cipher =
1008 CIPHER_AES_CCMP;
1009 }
1010 }
1011 }
1012 #endif
1013
1014 if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
1015 /*find and set wmm ie */
1016 woal_set_wmm_ies(ie, ie_len, sys_config);
1017 }
1018 /* If the security mode is configured as WEP or WPA-PSK,
1019 * it will disable 11n automatically, and if configured as
1020 * open(off) or wpa2-psk, it will automatically enable 11n */
1021 if ((sys_config->protocol == PROTOCOL_STATIC_WEP) ||
1022 (sys_config->protocol == PROTOCOL_WPA))
1023 enable_11n = MFALSE;
1024 if (!enable_11n) {
1025 woal_set_uap_ht_tx_cfg(priv, sys_config->bandcfg, MFALSE);
1026 woal_uap_set_11n_status(priv, sys_config, MLAN_ACT_DISABLE);
1027 } else {
1028 woal_set_uap_ht_tx_cfg(priv, sys_config->bandcfg, MTRUE);
1029 woal_uap_set_11n_status(priv, sys_config, MLAN_ACT_ENABLE);
1030 woal_set_get_tx_bf_cap(priv, MLAN_ACT_GET,
1031 &sys_config->tx_bf_cap);
1032 }
1033 if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv,
1034 MLAN_ACT_SET,
1035 MOAL_IOCTL_WAIT,
1036 sys_config)) {
1037 ret = -EFAULT;
1038 goto done;
1039 }
1040 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
1041 woal_enable_dfs_support(priv, &priv->chan);
1042 #endif
1043 done:
1044 kfree(sys_config);
1045 LEAVE();
1046 return ret;
1047 }
1048
1049 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1050 /**
1051 * @brief Request the driver to add a monitor interface
1052 *
1053 * @param wiphy A pointer to wiphy structure
1054 * @param name Virtual interface name
1055 * @param name_assign_type Interface name assignment type
1056 * @param flags Flags for the virtual interface
1057 * @param params A pointer to vif_params structure
1058 * @param new_dev Netdevice to be passed out
1059 *
1060 * @return 0 -- success, otherwise fail
1061 */
1062 static int
woal_cfg80211_add_mon_if(struct wiphy * wiphy,const char * name,unsigned char name_assign_type,u32 * flags,struct vif_params * params,struct net_device ** new_dev)1063 woal_cfg80211_add_mon_if(struct wiphy *wiphy,
1064 const char *name,
1065 unsigned char name_assign_type,
1066 u32 *flags, struct vif_params *params,
1067 struct net_device **new_dev)
1068 #else
1069 /**
1070 * @brief Request the driver to add a monitor interface
1071 *
1072 * @param wiphy A pointer to wiphy structure
1073 * @param name Virtual interface name
1074 * @param flags Flags for the virtual interface
1075 * @param params A pointer to vif_params structure
1076 * @param new_dev Netdevice to be passed out
1077 *
1078 * @return 0 -- success, otherwise fail
1079 */
1080 static int
1081 woal_cfg80211_add_mon_if(struct wiphy *wiphy,
1082 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
1083 const
1084 #endif
1085 char *name, u32 *flags, struct vif_params *params,
1086 struct net_device **new_dev)
1087 #endif
1088 {
1089 int ret = 0;
1090 moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
1091 moal_private *priv =
1092 (moal_private *)woal_get_priv(handle, MLAN_BSS_ROLE_STA);
1093 monitor_iface *mon_if = NULL;
1094 struct net_device *ndev = NULL;
1095 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1096 chan_band_info chan_info;
1097 #endif
1098 unsigned char name_assign_type_tmp = 0;
1099
1100 ENTER();
1101
1102 ASSERT_RTNL();
1103
1104 if (handle->mon_if) {
1105 PRINTM(MERROR, "%s: monitor interface exist: %s basedev %s\n",
1106 __func__, handle->mon_if->mon_ndev->name,
1107 handle->mon_if->base_ndev->name);
1108 ret = -EFAULT;
1109 goto fail;
1110 }
1111
1112 if (!priv) {
1113 PRINTM(MERROR, "add_mon_if: priv is NULL\n");
1114 ret = -EFAULT;
1115 goto fail;
1116 }
1117 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1118 name_assign_type_tmp = name_assign_type;
1119 #endif
1120 mon_if = woal_prepare_mon_if(priv, name, name_assign_type_tmp,
1121 CHANNEL_SPEC_SNIFFER_MODE);
1122 if (!mon_if) {
1123 PRINTM(MFATAL, "Prepare mon_if fail.\n");
1124 goto fail;
1125 }
1126
1127 ndev = mon_if->mon_ndev;
1128 dev_net_set(ndev, wiphy_net(wiphy));
1129 memcpy(ndev->perm_addr, wiphy->perm_addr, ETH_ALEN);
1130 memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN);
1131 SET_NETDEV_DEV(ndev, wiphy_dev(wiphy));
1132 ndev->ieee80211_ptr = &mon_if->wdev;
1133 mon_if->wdev.iftype = NL80211_IFTYPE_MONITOR;
1134 mon_if->wdev.wiphy = wiphy;
1135
1136 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1137 /* Set default band channel config */
1138 mon_if->band_chan_cfg.band = BAND_B | BAND_G;
1139 mon_if->band_chan_cfg.band |= BAND_GN;
1140 mon_if->band_chan_cfg.channel = 1;
1141 mon_if->band_chan_cfg.chan_bandwidth = CHANNEL_BW_20MHZ;
1142 memset(&chan_info, 0x00, sizeof(chan_info));
1143 chan_info.channel = 1;
1144 chan_info.is_11n_enabled = MTRUE;
1145 if (MLAN_STATUS_FAILURE ==
1146 woal_chandef_create(priv, &mon_if->chandef, &chan_info)) {
1147 ret = -EFAULT;
1148 goto fail;
1149 }
1150 if (MLAN_STATUS_SUCCESS != woal_set_net_monitor(priv, MOAL_IOCTL_WAIT,
1151 CHANNEL_SPEC_SNIFFER_MODE,
1152 0x7,
1153 &mon_if->
1154 band_chan_cfg)) {
1155 PRINTM(MERROR, "%s: woal_set_net_monitor fail\n", __func__);
1156 ret = -EFAULT;
1157 goto fail;
1158 }
1159 #endif
1160
1161 ret = register_netdevice(ndev);
1162 if (ret) {
1163 PRINTM(MFATAL, "register net_device failed, ret=%d\n", ret);
1164 free_netdev(ndev);
1165 goto fail;
1166 }
1167
1168 handle->mon_if = mon_if;
1169
1170 if (new_dev)
1171 *new_dev = ndev;
1172
1173 fail:
1174 LEAVE();
1175 return ret;
1176 }
1177
1178 #if defined(WIFI_DIRECT_SUPPORT)
1179 #if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
1180 /**
1181 * @brief Callback function for virtual interface
1182 * setup
1183 *
1184 * @param dev A pointer to structure net_device
1185 *
1186 * @return N/A
1187 */
1188 static void
woal_virt_if_setup(struct net_device * dev)1189 woal_virt_if_setup(struct net_device *dev)
1190 {
1191 ENTER();
1192 ether_setup(dev);
1193 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 11, 9)
1194 dev->needs_free_netdev = true;
1195 #else
1196 dev->destructor = free_netdev;
1197 #endif
1198 LEAVE();
1199 }
1200
1201 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1202 /**
1203 * @brief This function adds a new interface. It will
1204 * allocate, initialize and register the device.
1205 *
1206 * @param handle A pointer to moal_handle structure
1207 * @param bss_index BSS index number
1208 * @param name_assign_type Interface name assignment type
1209 * @param bss_type BSS type
1210 *
1211 * @return A pointer to the new priv structure
1212 */
1213 moal_private *
woal_alloc_virt_interface(moal_handle * handle,t_u8 bss_index,unsigned char name_assign_type,t_u8 bss_type,const char * name)1214 woal_alloc_virt_interface(moal_handle *handle, t_u8 bss_index,
1215 unsigned char name_assign_type,
1216 t_u8 bss_type, const char *name)
1217 #else
1218 /**
1219 * @brief This function adds a new interface. It will
1220 * allocate, initialize and register the device.
1221 *
1222 * @param handle A pointer to moal_handle structure
1223 * @param bss_index BSS index number
1224 * @param bss_type BSS type
1225 *
1226 * @return A pointer to the new priv structure
1227 */
1228 moal_private *
1229 woal_alloc_virt_interface(moal_handle *handle, t_u8 bss_index, t_u8 bss_type,
1230 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
1231 const
1232 #endif
1233 char *name)
1234 #endif
1235 {
1236 struct net_device *dev = NULL;
1237 moal_private *priv = NULL;
1238 ENTER();
1239
1240 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
1241 #ifndef MAX_WMM_QUEUE
1242 #define MAX_WMM_QUEUE 4
1243 #endif
1244 /* Allocate an Ethernet device */
1245 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
1246 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1247 dev = alloc_netdev_mq(sizeof(moal_private), name, name_assign_type,
1248 woal_virt_if_setup, MAX_WMM_QUEUE);
1249 #else
1250 dev = alloc_netdev_mq(sizeof(moal_private), name, NET_NAME_UNKNOWN,
1251 woal_virt_if_setup, MAX_WMM_QUEUE);
1252 #endif
1253 #else
1254 dev = alloc_netdev_mq(sizeof(moal_private), name, woal_virt_if_setup,
1255 MAX_WMM_QUEUE);
1256 #endif
1257 #else
1258 dev = alloc_netdev(sizeof(moal_private), name, woal_virt_if_setup);
1259 #endif
1260 if (!dev) {
1261 PRINTM(MFATAL, "Init virtual ethernet device failed\n");
1262 goto error;
1263 }
1264 /* Allocate device name */
1265 if ((dev_alloc_name(dev, name) < 0)) {
1266 PRINTM(MERROR, "Could not allocate device name\n");
1267 goto error;
1268 }
1269
1270 priv = (moal_private *)netdev_priv(dev);
1271 /* Save the priv to handle */
1272 handle->priv[bss_index] = priv;
1273
1274 /* Use the same handle structure */
1275 priv->phandle = handle;
1276 priv->netdev = dev;
1277 priv->bss_index = bss_index;
1278 priv->bss_type = bss_type;
1279 priv->bss_role = MLAN_BSS_ROLE_STA;
1280
1281 INIT_LIST_HEAD(&priv->tcp_sess_queue);
1282 spin_lock_init(&priv->tcp_sess_lock);
1283
1284 INIT_LIST_HEAD(&priv->tx_stat_queue);
1285 spin_lock_init(&priv->tx_stat_lock);
1286 spin_lock_init(&priv->connect_lock);
1287
1288 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
1289 SET_MODULE_OWNER(dev);
1290 #endif
1291
1292 PRINTM(MCMND, "Alloc virtual interface%s\n", dev->name);
1293
1294 LEAVE();
1295 return priv;
1296 error:
1297 if (dev)
1298 free_netdev(dev);
1299 LEAVE();
1300 return NULL;
1301 }
1302
1303 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1304 /**
1305 * @brief Request the driver to add a virtual interface
1306 *
1307 * @param wiphy A pointer to wiphy structure
1308 * @param name Virtual interface name
1309 * @param name_assign_type Interface name assignment type
1310 * @param type Virtual interface type
1311 * @param flags Flags for the virtual interface
1312 * @param params A pointer to vif_params structure
1313 * @param new_dev new net_device to return
1314 *
1315 * @return 0 -- success, otherwise fail
1316 */
1317 int
woal_cfg80211_add_virt_if(struct wiphy * wiphy,const char * name,unsigned char name_assign_type,enum nl80211_iftype type,u32 * flags,struct vif_params * params,struct net_device ** new_dev)1318 woal_cfg80211_add_virt_if(struct wiphy *wiphy,
1319 const char *name,
1320 unsigned char name_assign_type,
1321 enum nl80211_iftype type, u32 *flags,
1322 struct vif_params *params,
1323 struct net_device **new_dev)
1324 #else
1325 /**
1326 * @brief Request the driver to add a virtual interface
1327 *
1328 * @param wiphy A pointer to wiphy structure
1329 * @param name Virtual interface name
1330 * @param type Virtual interface type
1331 * @param flags Flags for the virtual interface
1332 * @param params A pointer to vif_params structure
1333 * @param new_dev new net_device to return
1334 *
1335 * @return 0 -- success, otherwise fail
1336 */
1337 int
1338 woal_cfg80211_add_virt_if(struct wiphy *wiphy,
1339 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
1340 const
1341 #endif
1342 char *name, enum nl80211_iftype type, u32 *flags,
1343 struct vif_params *params,
1344 struct net_device **new_dev)
1345 #endif
1346 {
1347 int ret = 0;
1348 struct net_device *ndev = NULL;
1349 moal_private *priv = NULL, *new_priv = NULL;
1350 moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
1351 struct wireless_dev *wdev = NULL;
1352 moal_private *vir_priv;
1353 int i = 0;
1354
1355 ENTER();
1356 ASSERT_RTNL();
1357 priv = (moal_private *)woal_get_priv_bss_type(handle,
1358 MLAN_BSS_TYPE_WIFIDIRECT);
1359 if (!priv || !priv->phandle) {
1360 PRINTM(MERROR, "priv or handle is NULL\n");
1361 LEAVE();
1362 return -EFAULT;
1363 }
1364 if (priv->phandle->drv_mode.intf_num == priv->phandle->priv_num) {
1365 PRINTM(MERROR, "max virtual interface limit reached\n");
1366 for (i = 0; i < priv->phandle->priv_num; i++) {
1367 vir_priv = priv->phandle->priv[i];
1368 if (vir_priv->bss_virtual) {
1369 woal_cfg80211_del_virt_if(wiphy,
1370 vir_priv->netdev);
1371 break;
1372 }
1373 }
1374 if (priv->phandle->drv_mode.intf_num == priv->phandle->priv_num) {
1375 LEAVE();
1376 return -ENOMEM;
1377 }
1378 }
1379 PRINTM(MMSG, "Add virtual interface %s\n", name);
1380 if ((type != NL80211_IFTYPE_P2P_CLIENT) &&
1381 (type != NL80211_IFTYPE_P2P_GO)) {
1382 PRINTM(MERROR, "Invalid iftype: %d\n", type);
1383 LEAVE();
1384 return -EINVAL;
1385 }
1386
1387 handle = priv->phandle;
1388 /* Cancel previous scan req */
1389 woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
1390 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1391 new_priv =
1392 woal_alloc_virt_interface(handle, handle->priv_num,
1393 name_assign_type,
1394 MLAN_BSS_TYPE_WIFIDIRECT, name);
1395 #else
1396 new_priv =
1397 woal_alloc_virt_interface(handle, handle->priv_num,
1398 MLAN_BSS_TYPE_WIFIDIRECT, name);
1399 #endif
1400 if (!new_priv) {
1401 PRINTM(MERROR, "Add virtual interface fail.");
1402 LEAVE();
1403 return -EFAULT;
1404 }
1405 handle->priv_num++;
1406
1407 wdev = (struct wireless_dev *)&new_priv->w_dev;
1408 memset(wdev, 0, sizeof(struct wireless_dev));
1409 ndev = new_priv->netdev;
1410 SET_NETDEV_DEV(ndev, wiphy_dev(wiphy));
1411 ndev->ieee80211_ptr = wdev;
1412 wdev->iftype = type;
1413 wdev->wiphy = wiphy;
1414 new_priv->wdev = wdev;
1415 new_priv->bss_virtual = MTRUE;
1416 new_priv->pa_netdev = priv->netdev;
1417
1418 woal_init_sta_dev(ndev, new_priv);
1419
1420 /* Initialize priv structure */
1421 woal_init_priv(new_priv, MOAL_IOCTL_WAIT);
1422 /** Init to GO/CLIENT mode */
1423 if (type == NL80211_IFTYPE_P2P_CLIENT)
1424 woal_cfg80211_init_p2p_client(new_priv);
1425 else if (type == NL80211_IFTYPE_P2P_GO)
1426 woal_cfg80211_init_p2p_go(new_priv);
1427 ret = register_netdevice(ndev);
1428 if (ret) {
1429 handle->priv[new_priv->bss_index] = NULL;
1430 handle->priv_num--;
1431 if (ndev->reg_state == NETREG_REGISTERED) {
1432 unregister_netdevice(ndev);
1433 free_netdev(ndev);
1434 ndev = NULL;
1435 }
1436 PRINTM(MFATAL, "register net_device failed, ret=%d\n", ret);
1437 goto done;
1438 }
1439 netif_carrier_off(ndev);
1440 woal_stop_queue(ndev);
1441 if (new_dev)
1442 *new_dev = ndev;
1443 #ifdef CONFIG_PROC_FS
1444 woal_create_proc_entry(new_priv);
1445 #ifdef PROC_DEBUG
1446 woal_debug_entry(new_priv);
1447 #endif /* PROC_DEBUG */
1448 #endif /* CONFIG_PROC_FS */
1449 done:
1450 LEAVE();
1451 return ret;
1452 }
1453
1454 /**
1455 * @brief Notify mlan BSS will be removed.
1456 *
1457 * @param priv A pointer to moal_private structure
1458 *
1459 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
1460 */
1461 mlan_status
woal_bss_remove(moal_private * priv)1462 woal_bss_remove(moal_private *priv)
1463 {
1464 mlan_ioctl_req *req = NULL;
1465 mlan_ds_bss *bss = NULL;
1466 mlan_status status;
1467
1468 ENTER();
1469
1470 /* Allocate an IOCTL request buffer */
1471 req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
1472 if (req == NULL) {
1473 status = MLAN_STATUS_FAILURE;
1474 goto done;
1475 }
1476
1477 /* Fill request buffer */
1478 bss = (mlan_ds_bss *)req->pbuf;
1479 bss->sub_command = MLAN_OID_BSS_REMOVE;
1480 req->req_id = MLAN_IOCTL_BSS;
1481 req->action = MLAN_ACT_SET;
1482 /* Send IOCTL request to MLAN */
1483 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1484
1485 done:
1486 if (status != MLAN_STATUS_PENDING)
1487 kfree(req);
1488 LEAVE();
1489 return status;
1490 }
1491
1492 /**
1493 * @brief This function removes an virtual interface.
1494 *
1495 * @param wiphy A pointer to the wiphy structure
1496 * @param dev A pointer to the net_device structure
1497 *
1498 * @return 0 -- success, otherwise fail
1499 */
1500 int
woal_cfg80211_del_virt_if(struct wiphy * wiphy,struct net_device * dev)1501 woal_cfg80211_del_virt_if(struct wiphy *wiphy, struct net_device *dev)
1502 {
1503 int ret = 0;
1504 int i = 0;
1505 moal_private *priv = NULL;
1506 moal_private *vir_priv = NULL;
1507 moal_private *remain_priv = NULL;
1508 moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
1509
1510 for (i = 0; i < handle->priv_num; i++) {
1511 vir_priv = handle->priv[i];
1512 if (vir_priv) {
1513 if (vir_priv->netdev == dev) {
1514 PRINTM(MMSG,
1515 "Del virtual interface %s, index=%d\n",
1516 dev->name, i);
1517 break;
1518 }
1519 }
1520 }
1521
1522 priv = (moal_private *)woal_get_priv_bss_type(handle,
1523 MLAN_BSS_TYPE_WIFIDIRECT);
1524 if (!priv)
1525 return ret;
1526 if (vir_priv && vir_priv->netdev == dev) {
1527 woal_stop_queue(dev);
1528 netif_carrier_off(dev);
1529 netif_device_detach(dev);
1530 if (handle->is_remain_timer_set) {
1531 woal_cancel_timer(&handle->remain_timer);
1532 woal_remain_timer_func(handle);
1533 }
1534
1535 /*** cancel pending scan */
1536 woal_cancel_scan(vir_priv, MOAL_IOCTL_WAIT);
1537
1538 woal_flush_tx_stat_queue(vir_priv);
1539
1540 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
1541 /* cancel previous remain on channel to avoid firmware hang */
1542 if (priv->phandle->remain_on_channel) {
1543 t_u8 channel_status;
1544 remain_priv =
1545 priv->phandle->priv[priv->phandle->
1546 remain_bss_index];
1547 if (remain_priv) {
1548 if (woal_cfg80211_remain_on_channel_cfg
1549 (remain_priv, MOAL_IOCTL_WAIT, MTRUE,
1550 &channel_status, NULL, 0, 0))
1551 PRINTM(MERROR,
1552 "del_virt_if: Fail to cancel remain on channel\n");
1553
1554 if (priv->phandle->cookie) {
1555 cfg80211_remain_on_channel_expired(
1556 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
1557 remain_priv->
1558 netdev,
1559 #else
1560 remain_priv->
1561 wdev,
1562 #endif
1563 priv->
1564 phandle->
1565 cookie,
1566 &priv->
1567 phandle->
1568 chan,
1569 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
1570 priv->
1571 phandle->
1572 channel_type,
1573 #endif
1574 GFP_ATOMIC);
1575 priv->phandle->cookie = 0;
1576 }
1577 priv->phandle->remain_on_channel = MFALSE;
1578 }
1579 }
1580 #endif
1581 woal_clear_all_mgmt_ies(vir_priv, MOAL_IOCTL_WAIT);
1582 woal_cfg80211_deinit_p2p(vir_priv);
1583 woal_bss_remove(vir_priv);
1584 #ifdef CONFIG_PROC_FS
1585 #ifdef PROC_DEBUG
1586 /* Remove proc debug */
1587 woal_debug_remove(vir_priv);
1588 #endif /* PROC_DEBUG */
1589 woal_proc_remove(vir_priv);
1590 #endif /* CONFIG_PROC_FS */
1591 /* Last reference is our one */
1592 #if CFG80211_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
1593 PRINTM(MINFO, "refcnt = %d\n", atomic_read(&dev->refcnt));
1594 #else
1595 PRINTM(MINFO, "refcnt = %d\n", netdev_refcnt_read(dev));
1596 #endif
1597 PRINTM(MINFO, "netdev_finish_unregister: %s\n", dev->name);
1598 /* Clear the priv in handle */
1599 vir_priv->phandle->priv[vir_priv->bss_index] = NULL;
1600 priv->phandle->priv_num--;
1601 if (dev->reg_state == NETREG_REGISTERED)
1602 unregister_netdevice(dev);
1603 }
1604 return ret;
1605 }
1606 #endif
1607 #endif
1608
1609 /**
1610 * @brief This function removes an virtual interface.
1611 *
1612 * @param handle A pointer to the moal_handle structure
1613 *
1614 * @return N/A
1615 */
1616 void
woal_remove_virtual_interface(moal_handle * handle)1617 woal_remove_virtual_interface(moal_handle *handle)
1618 {
1619 #ifdef WIFI_DIRECT_SUPPORT
1620 moal_private *priv = NULL;
1621 int vir_intf = 0;
1622 int i = 0;
1623 #endif
1624 ENTER();
1625 rtnl_lock();
1626 #ifdef WIFI_DIRECT_SUPPORT
1627 for (i = 0; i < handle->priv_num; i++) {
1628 priv = handle->priv[i];
1629 if (priv) {
1630 if (priv->bss_virtual) {
1631 PRINTM(MCMND, "Remove virtual interface %s\n",
1632 priv->netdev->name);
1633 #ifdef CONFIG_PROC_FS
1634 #ifdef PROC_DEBUG
1635 /* Remove proc debug */
1636 woal_debug_remove(priv);
1637 #endif /* PROC_DEBUG */
1638 woal_proc_remove(priv);
1639 #endif /* CONFIG_PROC_FS */
1640 netif_device_detach(priv->netdev);
1641 if (priv->netdev->reg_state ==
1642 NETREG_REGISTERED)
1643 unregister_netdevice(priv->netdev);
1644 handle->priv[i] = NULL;
1645 vir_intf++;
1646 }
1647 }
1648 }
1649 #endif
1650 if (handle->mon_if) {
1651 netif_device_detach(handle->mon_if->mon_ndev);
1652 if (handle->mon_if->mon_ndev->reg_state == NETREG_REGISTERED)
1653 unregister_netdevice(handle->mon_if->mon_ndev);
1654 handle->mon_if = NULL;
1655 }
1656 rtnl_unlock();
1657 #ifdef WIFI_DIRECT_SUPPORT
1658 handle->priv_num -= vir_intf;
1659 #endif
1660 LEAVE();
1661 }
1662
1663 /**
1664 * @brief This function check if uap interface is ready
1665 *
1666 * @param wiphy A pointer to wiphy structure
1667 * @param name Virtual interface name
1668 *
1669 * @return MTRUE/MFALSE;
1670 */
1671 static t_u8
woal_uap_interface_ready(struct wiphy * wiphy,char * name,struct net_device ** new_dev)1672 woal_uap_interface_ready(struct wiphy *wiphy, char *name,
1673 struct net_device **new_dev)
1674 {
1675 moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
1676 moal_private *priv = NULL;
1677 int i;
1678
1679 for (i = 0; i < handle->priv_num; i++) {
1680 priv = handle->priv[i];
1681 if (priv && (priv->bss_type == MLAN_BSS_TYPE_UAP) &&
1682 !strcmp(priv->netdev->name, name)) {
1683 priv->wdev->iftype = NL80211_IFTYPE_AP;
1684 *new_dev = priv->netdev;
1685 break;
1686 }
1687 }
1688 if (priv && *new_dev)
1689 return MTRUE;
1690 else
1691 return MFALSE;
1692 }
1693
1694 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
1695 #if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 37)
1696 /**
1697 * @brief Request the driver to add a virtual interface
1698 *
1699 * @param wiphy A pointer to wiphy structure
1700 * @param name Virtual interface name
1701 * @param type Virtual interface type
1702 * @param flags Flags for the virtual interface
1703 * @param params A pointer to vif_params structure
1704 *
1705 * @return A pointer to net_device -- success, otherwise null
1706 */
1707 struct net_device *
woal_cfg80211_add_virtual_intf(struct wiphy * wiphy,char * name,enum nl80211_iftype type,u32 * flags,struct vif_params * params)1708 woal_cfg80211_add_virtual_intf(struct wiphy *wiphy,
1709 char *name, enum nl80211_iftype type, u32 *flags,
1710 struct vif_params *params)
1711 #else
1712 /**
1713 * @brief Request the driver to add a virtual interface
1714 *
1715 * @param wiphy A pointer to wiphy structure
1716 * @param name Virtual interface name
1717 * @param type Virtual interface type
1718 * @param flags Flags for the virtual interface
1719 * @param params A pointer to vif_params structure
1720 *
1721 * @return 0 -- success, otherwise fail
1722 */
1723 int
1724 woal_cfg80211_add_virtual_intf(struct wiphy *wiphy,
1725 char *name, enum nl80211_iftype type, u32 *flags,
1726 struct vif_params *params)
1727 #endif
1728 #else
1729 #if CFG80211_VERSION_CODE < KERNEL_VERSION(4, 1, 0)
1730 /**
1731 * @brief Request the driver to add a virtual interface
1732 *
1733 * @param wiphy A pointer to wiphy structure
1734 * @param name Virtual interface name
1735 * @param type Virtual interface type
1736 * @param flags Flags for the virtual interface
1737 * @param params A pointer to vif_params structure
1738 *
1739 * @return A pointer to wireless_dev -- success, otherwise null
1740 */
1741 struct wireless_dev *
1742 woal_cfg80211_add_virtual_intf(struct wiphy *wiphy,
1743 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
1744 const
1745 #endif
1746 char *name, enum nl80211_iftype type, u32 *flags,
1747 struct vif_params *params)
1748 #else
1749 /**
1750 * @brief Request the driver to add a virtual interface
1751 *
1752 * @param wiphy A pointer to wiphy structure
1753 * @param name Virtual interface name
1754 * @param name_assign_type Interface name assignment type
1755 * @param type Virtual interface type
1756 * @param flags Flags for the virtual interface
1757 * @param params A pointer to vif_params structure
1758 *
1759 * @return A pointer to wireless_dev -- success, otherwise null
1760 */
1761 struct wireless_dev *
1762 woal_cfg80211_add_virtual_intf(struct wiphy *wiphy,
1763 const char *name,
1764 unsigned char name_assign_type,
1765 enum nl80211_iftype type,
1766 #if CFG80211_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
1767 u32 *flags,
1768 #endif
1769 struct vif_params *params)
1770 #endif
1771 #endif
1772 {
1773 struct net_device *ndev = NULL;
1774 int ret = 0;
1775 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
1776 u32 *flags = ¶ms->flags;
1777 #endif
1778
1779 ENTER();
1780 PRINTM(MIOCTL, "add virtual intf: %d name: %s\n", type, name);
1781 switch (type) {
1782 case NL80211_IFTYPE_MONITOR:
1783 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1784 ret = woal_cfg80211_add_mon_if(wiphy, name, name_assign_type,
1785 flags, params, &ndev);
1786 #else
1787 ret = woal_cfg80211_add_mon_if(wiphy, name, flags, params,
1788 &ndev);
1789 #endif
1790 break;
1791 #if defined(WIFI_DIRECT_SUPPORT)
1792 #if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
1793 case NL80211_IFTYPE_P2P_CLIENT:
1794 case NL80211_IFTYPE_P2P_GO:
1795 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1796 ret = woal_cfg80211_add_virt_if(wiphy, name, name_assign_type,
1797 type, flags, params, &ndev);
1798 #else
1799 ret = woal_cfg80211_add_virt_if(wiphy, name, type, flags,
1800 params, &ndev);
1801 #endif
1802 break;
1803 #endif
1804 #endif
1805 case NL80211_IFTYPE_AP:
1806 if (!woal_uap_interface_ready(wiphy, (char *)name, &ndev)) {
1807 PRINTM(MMSG,
1808 "Not support dynamically create %s UAP interface\n",
1809 name);
1810 ret = -EFAULT;
1811 }
1812 break;
1813 default:
1814 PRINTM(MWARN, "Not supported if type: %d\n", type);
1815 ret = -EFAULT;
1816 break;
1817 }
1818 LEAVE();
1819 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
1820 #if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 37)
1821 if (ret)
1822 return ERR_PTR(ret);
1823 else
1824 return ndev;
1825 #else
1826 return ret;
1827 #endif
1828 #else
1829 if (ret)
1830 return ERR_PTR(ret);
1831 else
1832 return ndev->ieee80211_ptr;
1833 #endif
1834 }
1835
1836 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
1837 /**
1838 * @brief Request the driver to del a virtual interface
1839 *
1840 * @param wiphy A pointer to wiphy structure
1841 * @param dev The pointer to net_device
1842 *
1843 * @return 0 -- success, otherwise fail
1844 */
1845 int
woal_cfg80211_del_virtual_intf(struct wiphy * wiphy,struct net_device * dev)1846 woal_cfg80211_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev)
1847 #else
1848 /**
1849 * @brief Request the driver to del a virtual interface
1850 *
1851 * @param wiphy A pointer to wiphy structure
1852 * @param wdev The pointer to wireless_dev
1853 *
1854 * @return 0 -- success, otherwise fail
1855 */
1856 int
1857 woal_cfg80211_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
1858 #endif
1859 {
1860 int ret = 0;
1861 moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
1862 int i;
1863 moal_private *vir_priv = NULL;
1864 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
1865 struct net_device *dev = wdev->netdev;
1866 #endif
1867 ENTER();
1868
1869 PRINTM(MIOCTL, "del virtual intf %s\n", dev->name);
1870 ASSERT_RTNL();
1871 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_MONITOR) {
1872 if ((handle->mon_if) && (handle->mon_if->mon_ndev == dev)) {
1873 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1874 if (MLAN_STATUS_SUCCESS !=
1875 woal_set_net_monitor(handle->mon_if->priv,
1876 MOAL_IOCTL_WAIT, MFALSE, 0,
1877 NULL)) {
1878 PRINTM(MERROR,
1879 "%s: woal_set_net_monitor fail\n",
1880 __func__);
1881 ret = -EFAULT;
1882 }
1883 #endif
1884 handle->mon_if = NULL;
1885 }
1886 unregister_netdevice(dev);
1887 LEAVE();
1888 return ret;
1889 }
1890 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
1891 for (i = 0; i < handle->priv_num; i++) {
1892 vir_priv = handle->priv[i];
1893 if (vir_priv) {
1894 if (vir_priv->netdev == dev) {
1895 PRINTM(MMSG,
1896 "Del virtual interface %s, index=%d\n",
1897 dev->name, i);
1898 break;
1899 }
1900 }
1901 }
1902 if (vir_priv && vir_priv->bss_type == MLAN_BSS_TYPE_UAP) {
1903 woal_cfg80211_del_beacon(wiphy, dev);
1904 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
1905 vir_priv->wdev->beacon_interval = 0;
1906 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
1907 memset(&vir_priv->wdev->chandef, 0,
1908 sizeof(vir_priv->wdev->chandef));
1909 #endif
1910 #endif
1911 vir_priv->wdev->ssid_len = 0;
1912 PRINTM(MMSG, "Skip del UAP virtual interface %s",
1913 dev->name);
1914 }
1915 LEAVE();
1916 return ret;
1917 }
1918 #if defined(WIFI_DIRECT_SUPPORT)
1919 #if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
1920 ret = woal_cfg80211_del_virt_if(wiphy, dev);
1921 #endif
1922 #endif
1923 LEAVE();
1924 return ret;
1925 }
1926
1927 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
1928 /**
1929 * @brief initialize AP or GO parameters
1930
1931 *
1932 * @param wiphy A pointer to wiphy structure
1933 * @param dev A pointer to net_device structure
1934 * @param params A pointer to cfg80211_ap_settings structure
1935 * @return 0 -- success, otherwise fail
1936 */
1937 int
woal_cfg80211_add_beacon(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_ap_settings * params)1938 woal_cfg80211_add_beacon(struct wiphy *wiphy,
1939 struct net_device *dev,
1940 struct cfg80211_ap_settings *params)
1941 #else
1942 /**
1943 * @brief initialize AP or GO parameters
1944
1945 *
1946 * @param wiphy A pointer to wiphy structure
1947 * @param dev A pointer to net_device structure
1948 * @param params A pointer to beacon_parameters structure
1949 * @return 0 -- success, otherwise fail
1950 */
1951 int
1952 woal_cfg80211_add_beacon(struct wiphy *wiphy,
1953 struct net_device *dev,
1954 struct beacon_parameters *params)
1955 #endif
1956 {
1957 moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
1958 int ret = 0;
1959 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
1960 t_u8 wait_option = MOAL_IOCTL_WAIT;
1961 #endif
1962 ENTER();
1963
1964 PRINTM(MMSG, "wlan: Starting AP\n");
1965 #ifdef STA_CFG80211
1966 /*** cancel pending scan */
1967 woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
1968 #endif
1969
1970 if (!params) {
1971 LEAVE();
1972 return -EFAULT;
1973 }
1974 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
1975 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1976 priv->channel =
1977 ieee80211_frequency_to_channel(params->chandef.chan->
1978 center_freq);
1979 #else
1980 priv->channel =
1981 ieee80211_frequency_to_channel(params->channel->center_freq);
1982 #endif
1983 #endif
1984 /* bss config */
1985 if (MLAN_STATUS_SUCCESS != woal_cfg80211_beacon_config(priv, params)) {
1986 ret = -EFAULT;
1987 goto done;
1988 }
1989
1990 /* set mgmt frame ies */
1991 ret = woal_cfg80211_mgmt_frame_ie(priv,
1992 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
1993 params->tail, params->tail_len, NULL,
1994 0, NULL, 0, NULL, 0, MGMT_MASK_BEACON
1995 #else
1996 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
1997 params->beacon.tail,
1998 params->beacon.tail_len,
1999 params->beacon.proberesp_ies,
2000 params->beacon.proberesp_ies_len,
2001 params->beacon.assocresp_ies,
2002 params->beacon.assocresp_ies_len,
2003 #else
2004 params->tail, params->tail_len,
2005 params->proberesp_ies,
2006 params->proberesp_ies_len,
2007 params->assocresp_ies,
2008 params->assocresp_ies_len,
2009 #endif
2010 NULL, 0,
2011 MGMT_MASK_BEACON |
2012 MGMT_MASK_PROBE_RESP |
2013 MGMT_MASK_ASSOC_RESP
2014 #endif
2015 , MOAL_IOCTL_WAIT);
2016 if (ret)
2017 goto done;
2018
2019 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
2020 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
2021 if (params->beacon.beacon_ies && params->beacon.beacon_ies_len) {
2022 ret = woal_cfg80211_mgmt_frame_ie(priv,
2023 params->beacon.beacon_ies,
2024 params->beacon.beacon_ies_len,
2025 NULL, 0, NULL, 0, NULL, 0,
2026 MGMT_MASK_BEACON_WPS_P2P,
2027 MOAL_IOCTL_WAIT);
2028 if (ret) {
2029 PRINTM(MERROR, "Failed to set beacon wps/p2p ie\n");
2030 goto done;
2031 }
2032 }
2033 #else
2034 if (params->beacon_ies && params->beacon_ies_len) {
2035 ret = woal_cfg80211_mgmt_frame_ie(priv,
2036 params->beacon_ies,
2037 params->beacon_ies_len, NULL,
2038 0, NULL, 0, NULL, 0,
2039 MGMT_MASK_BEACON_WPS_P2P,
2040 MOAL_IOCTL_WAIT);
2041 if (ret) {
2042 PRINTM(MERROR, "Failed to set beacon wps/p2p ie\n");
2043 goto done;
2044 }
2045 }
2046 #endif
2047 #endif
2048 priv->uap_host_based = MTRUE;
2049
2050 /* if the bss is stopped, then start it */
2051 if (priv->bss_started == MFALSE) {
2052 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2053 if (dfs_offload)
2054 wait_option = MOAL_NO_WAIT;
2055 #endif
2056 if (MLAN_STATUS_SUCCESS !=
2057 woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START)) {
2058 priv->uap_host_based = MFALSE;
2059 ret = -EFAULT;
2060 goto done;
2061 }
2062 }
2063 PRINTM(MMSG, "wlan: AP started\n");
2064 done:
2065 LEAVE();
2066 return ret;
2067 }
2068
2069 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
2070 /**
2071 * @brief set AP or GO parameter
2072 *
2073 * @param wiphy A pointer to wiphy structure
2074 * @param dev A pointer to net_device structure
2075 * @param params A pointer to cfg80211_beacon_data structure
2076 * @return 0 -- success, otherwise fail
2077 */
2078 int
woal_cfg80211_set_beacon(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_beacon_data * params)2079 woal_cfg80211_set_beacon(struct wiphy *wiphy,
2080 struct net_device *dev,
2081 struct cfg80211_beacon_data *params)
2082 #else
2083 /**
2084 * @brief set AP or GO parameter
2085 *
2086 * @param wiphy A pointer to wiphy structure
2087 * @param dev A pointer to net_device structure
2088 * @param params A pointer to beacon_parameters structure
2089 * @return 0 -- success, otherwise fail
2090 */
2091 int
2092 woal_cfg80211_set_beacon(struct wiphy *wiphy,
2093 struct net_device *dev,
2094 struct beacon_parameters *params)
2095 #endif
2096 {
2097 moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
2098 int ret = 0;
2099
2100 ENTER();
2101
2102 PRINTM(MIOCTL, "set beacon\n");
2103 if (params != NULL) {
2104 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
2105 if (params->tail && params->tail_len) {
2106 ret = woal_cfg80211_mgmt_frame_ie(priv,
2107 params->tail,
2108 params->tail_len,
2109 NULL, 0, NULL, 0,
2110 NULL, 0,
2111 MGMT_MASK_BEACON,
2112 MOAL_IOCTL_WAIT);
2113 if (ret)
2114 goto done;
2115 }
2116 #else
2117 t_u16 mask = 0;
2118 if (params->tail && params->tail_len)
2119 mask |= MGMT_MASK_BEACON;
2120 if (params->proberesp_ies && params->proberesp_ies_len)
2121 mask |= MGMT_MASK_PROBE_RESP;
2122 if (params->assocresp_ies && params->assocresp_ies_len)
2123 mask |= MGMT_MASK_ASSOC_RESP;
2124 PRINTM(MIOCTL, "Set beacon: mask=0x%x\n", mask);
2125 if (mask) {
2126 ret = woal_cfg80211_mgmt_frame_ie(priv, params->tail,
2127 params->tail_len,
2128 params->proberesp_ies,
2129 params->
2130 proberesp_ies_len,
2131 params->assocresp_ies,
2132 params->
2133 assocresp_ies_len,
2134 NULL, 0, mask,
2135 MOAL_IOCTL_WAIT);
2136 if (ret)
2137 goto done;
2138 }
2139 if (params->beacon_ies && params->beacon_ies_len) {
2140 ret = woal_cfg80211_mgmt_frame_ie(priv,
2141 params->beacon_ies,
2142 params->
2143 beacon_ies_len, NULL,
2144 0, NULL, 0, NULL, 0,
2145 MGMT_MASK_BEACON_WPS_P2P,
2146 MOAL_IOCTL_WAIT);
2147 if (ret) {
2148 PRINTM(MERROR,
2149 "Failed to set beacon wps/p2p ie\n");
2150 goto done;
2151 }
2152 }
2153 #endif
2154 }
2155
2156 done:
2157 LEAVE();
2158 return ret;
2159 }
2160
2161 /**
2162 * @brief reset AP or GO parameters
2163 *
2164 * @param wiphy A pointer to wiphy structure
2165 * @param dev A pointer to net_device structure
2166 *
2167 * @return 0 -- success, otherwise fail
2168 */
2169 int
woal_cfg80211_del_beacon(struct wiphy * wiphy,struct net_device * dev)2170 woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
2171 {
2172 moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
2173 int ret = 0;
2174 #ifdef STA_SUPPORT
2175 moal_private *pmpriv = NULL;
2176 #endif
2177
2178 ENTER();
2179
2180 priv->phandle->driver_state = woal_check_driver_status(priv->phandle);
2181 if (priv->phandle->driver_state) {
2182 PRINTM(MERROR,
2183 "Block woal_cfg80211_del_beacon in abnormal driver state\n");
2184 LEAVE();
2185 return -EFAULT;
2186 }
2187 priv->uap_host_based = MFALSE;
2188 PRINTM(MMSG, "wlan: Stoping AP\n");
2189 #ifdef STA_SUPPORT
2190 woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
2191 #endif
2192 memset(priv->dscp_map, 0xFF, sizeof(priv->dscp_map));
2193 woal_deauth_all_station(priv);
2194 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2195 if (dfs_offload)
2196 woal_cancel_cac_block(priv);
2197 #endif
2198 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
2199 memset(&priv->chan, 0, sizeof(struct cfg80211_chan_def));
2200 if (priv->phandle->is_cac_timer_set &&
2201 priv->bss_index == priv->phandle->cac_bss_index) {
2202 woal_cancel_timer(&priv->phandle->cac_timer);
2203 priv->phandle->is_cac_timer_set = MFALSE;
2204 /* Make sure Chan Report is cancelled */
2205 woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT);
2206 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2207 cfg80211_cac_event(priv->netdev, &priv->phandle->dfs_channel,
2208 NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
2209 #else
2210 cfg80211_cac_event(priv->netdev, NL80211_RADAR_CAC_ABORTED,
2211 GFP_KERNEL);
2212 #endif
2213 memset(&priv->phandle->dfs_channel, 0,
2214 sizeof(struct cfg80211_chan_def));
2215 priv->phandle->cac_bss_index = 0xff;
2216 }
2217 if (priv->csa_workqueue)
2218 flush_workqueue(priv->csa_workqueue);
2219 #endif
2220 /* if the bss is still running, then stop it */
2221 if (priv->bss_started == MTRUE) {
2222 if (MLAN_STATUS_SUCCESS !=
2223 woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP)) {
2224 ret = -EFAULT;
2225 goto done;
2226 }
2227 if (MLAN_STATUS_SUCCESS !=
2228 woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_RESET)) {
2229 ret = -EFAULT;
2230 goto done;
2231 }
2232 /* Set WLAN MAC addresses */
2233 if (MLAN_STATUS_SUCCESS != woal_request_set_mac_address(priv)) {
2234 PRINTM(MERROR, "Set MAC address failed\n");
2235 ret = -EFAULT;
2236 goto done;
2237 }
2238 }
2239 woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_WAIT);
2240 #ifdef STA_SUPPORT
2241 if (!woal_is_any_interface_active(priv->phandle)) {
2242 pmpriv = woal_get_priv((moal_handle *)priv->phandle,
2243 MLAN_BSS_ROLE_STA);
2244 if (pmpriv)
2245 woal_set_scan_time(pmpriv, ACTIVE_SCAN_CHAN_TIME,
2246 PASSIVE_SCAN_CHAN_TIME,
2247 SPECIFIC_SCAN_CHAN_TIME);
2248 }
2249 #endif
2250
2251 priv->cipher = 0;
2252 memset(priv->uap_wep_key, 0, sizeof(priv->uap_wep_key));
2253 priv->channel = 0;
2254 PRINTM(MMSG, "wlan: AP stopped\n");
2255 done:
2256 LEAVE();
2257 return ret;
2258 }
2259
2260 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
2261 /**
2262 * @brief change BSS
2263 *
2264 * @param wiphy A pointer to wiphy structure
2265 * @param dev A pointer to net_device structure
2266 * @param params A pointer to bss_parameters structure
2267 *
2268 * @return 0 -- success, otherwise fail
2269 */
2270 int
woal_cfg80211_change_bss(struct wiphy * wiphy,struct net_device * dev,struct bss_parameters * params)2271 woal_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev,
2272 struct bss_parameters *params)
2273 {
2274 int ret = 0;
2275 t_u8 change = MFALSE;
2276 mlan_uap_bss_param *sys_config = NULL;
2277 u8 bss_started = MFALSE;
2278 t_u8 pkt_forward_ctl;
2279 moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
2280
2281 ENTER();
2282 PRINTM(MIOCTL, "isolate=%d\n", params->ap_isolate);
2283
2284 sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
2285 if (!sys_config) {
2286 PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
2287 LEAVE();
2288 return -EFAULT;
2289 }
2290
2291 if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv,
2292 MLAN_ACT_GET,
2293 MOAL_IOCTL_WAIT,
2294 sys_config)) {
2295 PRINTM(MERROR, "Error getting AP confiruration\n");
2296 ret = -EFAULT;
2297 goto done;
2298 }
2299
2300 pkt_forward_ctl = sys_config->pkt_forward_ctl;
2301 if (params->ap_isolate) {
2302 /** disable packet forwarding */
2303 sys_config->pkt_forward_ctl |= PKT_FWD_INTRA_BCAST;
2304 sys_config->pkt_forward_ctl |= PKT_FWD_INTRA_UCAST;
2305 } else {
2306 sys_config->pkt_forward_ctl &= ~PKT_FWD_INTRA_BCAST;
2307 sys_config->pkt_forward_ctl &= ~PKT_FWD_INTRA_UCAST;
2308 }
2309 if (pkt_forward_ctl != sys_config->pkt_forward_ctl) {
2310 change = MTRUE;
2311 PRINTM(MIOCTL, "ap_isolate=%xd\n", params->ap_isolate);
2312 }
2313 if (change) {
2314 if (priv->bss_started == MTRUE) {
2315 bss_started = MTRUE;
2316 woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP);
2317 }
2318 if (MLAN_STATUS_SUCCESS == woal_set_get_sys_config(priv,
2319 MLAN_ACT_SET,
2320 MOAL_IOCTL_WAIT,
2321 sys_config))
2322 ret = 0;
2323 if (bss_started)
2324 woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START);
2325 }
2326 done:
2327 kfree(sys_config);
2328 LEAVE();
2329 return ret;
2330 }
2331 #endif
2332
2333 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
2334 /**
2335 * @brief del station
2336 *
2337 * @param wiphy A pointer to wiphy structure
2338 * @param dev A pointer to net_device structure
2339 * @param param A pointer tostation_del_parameters structure
2340 *
2341 * @return 0 -- success, otherwise fail
2342 */
2343 #else
2344 /**
2345 * @brief del station
2346 *
2347 * @param wiphy A pointer to wiphy structure
2348 * @param dev A pointer to net_device structure
2349 * @param mac_addr A pointer to station mac address
2350 *
2351 * @return 0 -- success, otherwise fail
2352 */
2353 #endif
2354 int
woal_cfg80211_del_station(struct wiphy * wiphy,struct net_device * dev,struct station_del_parameters * param)2355 woal_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
2356 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
2357 struct station_del_parameters *param)
2358 #else
2359 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
2360 const u8 *mac_addr)
2361 #else
2362 u8 *mac_addr)
2363 #endif
2364 #endif
2365 {
2366 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
2367 const u8 *mac_addr = NULL;
2368 #endif
2369 u16 reason_code = REASON_CODE_DEAUTH_LEAVING;
2370 moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
2371 ENTER();
2372 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
2373 if (priv->phandle->is_cac_timer_set &&
2374 priv->bss_index == priv->phandle->cac_bss_index) {
2375 woal_cancel_timer(&priv->phandle->cac_timer);
2376 priv->phandle->is_cac_timer_set = MFALSE;
2377 /* Make sure Chan Report is cancelled */
2378 woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT);
2379 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2380 cfg80211_cac_event(priv->netdev, &priv->phandle->dfs_channel,
2381 NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
2382 #else
2383 cfg80211_cac_event(priv->netdev, NL80211_RADAR_CAC_ABORTED,
2384 GFP_KERNEL);
2385 #endif
2386 memset(&priv->phandle->dfs_channel, 0,
2387 sizeof(struct cfg80211_chan_def));
2388 priv->phandle->cac_bss_index = 0xff;
2389 }
2390 #endif
2391 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2392 if (dfs_offload)
2393 woal_cancel_cac_block(priv);
2394 #endif
2395
2396 if (priv->media_connected == MFALSE) {
2397 PRINTM(MINFO, "cfg80211: Media not connected!\n");
2398 LEAVE();
2399 return 0;
2400 }
2401 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
2402 if (param) {
2403 mac_addr = param->mac;
2404 reason_code = param->reason_code;
2405 }
2406 #endif
2407 /** we will not send deauth to p2p interface, it might cause WPS failure */
2408 if (mac_addr) {
2409 PRINTM(MMSG, "wlan: deauth station " MACSTR "\n",
2410 MAC2STR(mac_addr));
2411 #ifdef WIFI_DIRECT_SUPPORT
2412 if (!priv->phandle->is_go_timer_set ||
2413 priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT)
2414 #endif
2415 woal_deauth_station(priv, (u8 *)mac_addr, reason_code);
2416 } else {
2417 PRINTM(MIOCTL, "del all station\n");
2418 }
2419 LEAVE();
2420 return 0;
2421
2422 }
2423
2424 /**
2425 * @brief Get station info
2426 *
2427 * @param wiphy A pointer to wiphy structure
2428 * @param dev A pointer to net_device structure
2429 * @param mac A pointer to station mac address
2430 * @param stainfo A pointer to station_info structure
2431 *
2432 * @return 0 -- success, otherwise fail
2433 */
2434 int
woal_uap_cfg80211_get_station(struct wiphy * wiphy,struct net_device * dev,const u8 * mac,struct station_info * stainfo)2435 woal_uap_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
2436 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
2437 const u8 *mac,
2438 #else
2439 u8 *mac,
2440 #endif
2441 struct station_info *stainfo)
2442 {
2443 moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
2444 int ret = -EFAULT;
2445 int i = 0;
2446 mlan_ds_get_info *info = NULL;
2447 mlan_ioctl_req *ioctl_req = NULL;
2448 mlan_status status = MLAN_STATUS_SUCCESS;
2449
2450 ENTER();
2451 if (priv->media_connected == MFALSE) {
2452 PRINTM(MINFO, "cfg80211: Media not connected!\n");
2453 LEAVE();
2454 return -ENOENT;
2455 }
2456
2457 /* Allocate an IOCTL request buffer */
2458 ioctl_req =
2459 (mlan_ioctl_req *)
2460 woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
2461 if (ioctl_req == NULL) {
2462 ret = -ENOMEM;
2463 goto done;
2464 }
2465
2466 info = (mlan_ds_get_info *)ioctl_req->pbuf;
2467 info->sub_command = MLAN_OID_UAP_STA_LIST;
2468 ioctl_req->req_id = MLAN_IOCTL_GET_INFO;
2469 ioctl_req->action = MLAN_ACT_GET;
2470
2471 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2472 if (status != MLAN_STATUS_SUCCESS)
2473 goto done;
2474 for (i = 0; i < info->param.sta_list.sta_count; i++) {
2475 if (!memcmp
2476 (info->param.sta_list.info[i].mac_address, mac, ETH_ALEN)) {
2477 PRINTM(MIOCTL, "Get station: " MACSTR " RSSI=%d\n",
2478 MAC2STR(mac),
2479 (int)info->param.sta_list.info[i].rssi);
2480 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
2481 stainfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME) |
2482 BIT(NL80211_STA_INFO_SIGNAL);
2483 #else
2484 stainfo->filled =
2485 STATION_INFO_INACTIVE_TIME |
2486 STATION_INFO_SIGNAL;
2487 #endif
2488 stainfo->inactive_time = 0;
2489 stainfo->signal = info->param.sta_list.info[i].rssi;
2490 ret = 0;
2491 break;
2492 }
2493 }
2494 done:
2495 if (status != MLAN_STATUS_PENDING)
2496 kfree(ioctl_req);
2497 LEAVE();
2498 return ret;
2499 }
2500
2501 /**
2502 * @brief Request the driver to dump the station information
2503 *
2504 * @param wiphy A pointer to wiphy structure
2505 * @param dev A pointer to net_device structure
2506 * @param idx Station index
2507 * @param mac MAC address of the station
2508 * @param sinfo A pointer to station_info structure
2509 *
2510 * @return 0 -- success, otherwise fail
2511 */
2512 int
woal_uap_cfg80211_dump_station(struct wiphy * wiphy,struct net_device * dev,int idx,t_u8 * mac,struct station_info * sinfo)2513 woal_uap_cfg80211_dump_station(struct wiphy *wiphy,
2514 struct net_device *dev, int idx,
2515 t_u8 *mac, struct station_info *sinfo)
2516 {
2517 moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
2518 int ret = -EFAULT;
2519 mlan_ds_get_info *info = NULL;
2520 mlan_ioctl_req *ioctl_req = NULL;
2521 mlan_status status = MLAN_STATUS_SUCCESS;
2522
2523 ENTER();
2524 if (priv->media_connected == MFALSE) {
2525 PRINTM(MINFO, "cfg80211: Media not connected!\n");
2526 LEAVE();
2527 return -ENOENT;
2528 }
2529
2530 /* Allocate an IOCTL request buffer */
2531 ioctl_req =
2532 (mlan_ioctl_req *)
2533 woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
2534 if (ioctl_req == NULL) {
2535 ret = -ENOMEM;
2536 goto done;
2537 }
2538
2539 info = (mlan_ds_get_info *)ioctl_req->pbuf;
2540 info->sub_command = MLAN_OID_UAP_STA_LIST;
2541 ioctl_req->req_id = MLAN_IOCTL_GET_INFO;
2542 ioctl_req->action = MLAN_ACT_GET;
2543
2544 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2545 if (status != MLAN_STATUS_SUCCESS)
2546 goto done;
2547 if (idx >= info->param.sta_list.sta_count) {
2548 ret = -EFAULT;
2549 goto done;
2550 }
2551 ret = 0;
2552 memcpy(mac, info->param.sta_list.info[idx].mac_address, ETH_ALEN);
2553 PRINTM(MIOCTL, "Dump station: " MACSTR " RSSI=%d\n", MAC2STR(mac),
2554 (int)info->param.sta_list.info[idx].rssi);
2555 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
2556 sinfo->filled =
2557 BIT(NL80211_STA_INFO_INACTIVE_TIME) |
2558 BIT(NL80211_STA_INFO_SIGNAL);
2559 #else
2560 sinfo->filled = STATION_INFO_INACTIVE_TIME | STATION_INFO_SIGNAL;
2561 #endif
2562 sinfo->inactive_time = 0;
2563 sinfo->signal = info->param.sta_list.info[idx].rssi;
2564 done:
2565 if (status != MLAN_STATUS_PENDING)
2566 kfree(ioctl_req);
2567 LEAVE();
2568 return ret;
2569 }
2570
2571 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
2572 /**
2573 * @brief set mac filter
2574 *
2575 * @param wiphy A pointer to wiphy structure
2576 * @param dev A pointer to net_device structure
2577 * @param params A pointer to cfg80211_acl_data structure
2578 *
2579 * @return 0 -- success, otherwise fail
2580 */
2581 int
woal_cfg80211_set_mac_acl(struct wiphy * wiphy,struct net_device * dev,const struct cfg80211_acl_data * params)2582 woal_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *dev,
2583 const struct cfg80211_acl_data *params)
2584 {
2585 int ret = -EFAULT;
2586 mlan_uap_bss_param *sys_config = NULL;
2587 moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
2588 u8 bss_started = MFALSE;
2589 ENTER();
2590
2591 PRINTM(MIOCTL, "Set mac acl, entries=%d, policy=%d\n",
2592 params->n_acl_entries, params->acl_policy);
2593 sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
2594 if (!sys_config) {
2595 PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
2596 LEAVE();
2597 return -EFAULT;
2598 }
2599 /* Initialize the uap bss values which are uploaded from firmware */
2600 if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv,
2601 MLAN_ACT_GET,
2602 MOAL_IOCTL_WAIT,
2603 sys_config)) {
2604 PRINTM(MERROR, "Error getting AP confiruration\n");
2605 ret = -EFAULT;
2606 goto done;
2607 }
2608 memset(&sys_config->filter, 0, sizeof(mac_filter));
2609 if (params->n_acl_entries <= MAX_MAC_FILTER_NUM)
2610 sys_config->filter.mac_count = params->n_acl_entries;
2611 else
2612 sys_config->filter.mac_count = MAX_MAC_FILTER_NUM;
2613
2614 if (params->acl_policy == NL80211_ACL_POLICY_DENY_UNLESS_LISTED)
2615 sys_config->filter.filter_mode = MAC_FILTER_MODE_ALLOW_MAC;
2616 else if (params->acl_policy == NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED)
2617 sys_config->filter.filter_mode = MAC_FILTER_MODE_BLOCK_MAC;
2618 memcpy(sys_config->filter.mac_list, params->mac_addrs,
2619 sys_config->filter.mac_count * sizeof(mlan_802_11_mac_addr));
2620 if (priv->bss_started == MTRUE) {
2621 bss_started = MTRUE;
2622 woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP);
2623 }
2624 if (MLAN_STATUS_SUCCESS == woal_set_get_sys_config(priv,
2625 MLAN_ACT_SET,
2626 MOAL_IOCTL_WAIT,
2627 sys_config))
2628 ret = 0;
2629 done:
2630 kfree(sys_config);
2631 if (bss_started)
2632 woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START);
2633 LEAVE();
2634 return ret;
2635 }
2636 #endif
2637
2638 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
2639 /**
2640 * @brief Set txq parameters
2641
2642 * @param wiphy A pointer to wiphy structure
2643 * @param dev A pointer to net_device structure
2644 * @param params A pointer to ieee80211_txq_params structure
2645 *
2646 * @return 0 -- success, otherwise fail
2647 */
2648 int
woal_cfg80211_set_txq_params(struct wiphy * wiphy,struct net_device * dev,struct ieee80211_txq_params * params)2649 woal_cfg80211_set_txq_params(struct wiphy *wiphy, struct net_device *dev,
2650 struct ieee80211_txq_params *params)
2651 {
2652 int ret = 0;
2653 u8 ac = 0;
2654 wmm_parameter_t ap_wmm_para;
2655 moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
2656
2657 ENTER();
2658
2659 /* AC_BE: 0, AC_BK:1, AC_VI: 2, AC_VO:3 */
2660 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
2661 switch (params->ac) {
2662 case NL80211_AC_VO:
2663 ac = 3;
2664 break;
2665 case NL80211_AC_VI:
2666 ac = 2;
2667 break;
2668 case NL80211_AC_BK:
2669 ac = 1;
2670 break;
2671 case NL80211_AC_BE:
2672 ac = 0;
2673 break;
2674 default:
2675 break;
2676 }
2677 #else
2678 switch (params->queue) {
2679 case NL80211_TXQ_Q_VO:
2680 ac = 3;
2681 break;
2682 case NL80211_TXQ_Q_VI:
2683 ac = 2;
2684 break;
2685 case NL80211_TXQ_Q_BK:
2686 ac = 1;
2687 break;
2688 case NL80211_TXQ_Q_BE:
2689 ac = 0;
2690 break;
2691 default:
2692 break;
2693 }
2694 #endif
2695
2696 PRINTM(MMSG, "Set AC=%d, txop=%d cwmin=%d, cwmax=%d aifs=%d\n", ac,
2697 params->txop, params->cwmin, params->cwmax, params->aifs);
2698
2699 memset(&ap_wmm_para, 0, sizeof(wmm_parameter_t));
2700
2701 if (MLAN_STATUS_SUCCESS !=
2702 woal_set_get_ap_wmm_para(priv, MLAN_ACT_GET, &ap_wmm_para)) {
2703 PRINTM(MERROR, "wlan: We don't support AP WMM parameter\n");
2704 LEAVE();
2705 return ret;
2706 }
2707 ap_wmm_para.ac_params[ac].aci_aifsn.aifsn = params->aifs;
2708 ap_wmm_para.ac_params[ac].ecw.ecw_max = ilog2(params->cwmax + 1);
2709 ap_wmm_para.ac_params[ac].ecw.ecw_min = ilog2(params->cwmin + 1);
2710 ap_wmm_para.ac_params[ac].tx_op_limit = params->txop;
2711 if (MLAN_STATUS_SUCCESS !=
2712 woal_set_get_ap_wmm_para(priv, MLAN_ACT_SET, &ap_wmm_para)) {
2713 PRINTM(MERROR, "wlan: Fail to set AP WMM parameter\n");
2714 ret = -EFAULT;
2715 }
2716 LEAVE();
2717 return ret;
2718 }
2719 #endif
2720
2721 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
2722 /**
2723 * @brief cac timer call back function.
2724 *
2725 * @param context a pointer to moal_handle
2726 *
2727 * @return N/A
2728 */
2729 void
woal_cac_timer_func(void * context)2730 woal_cac_timer_func(void *context)
2731 {
2732 moal_handle *handle = (moal_handle *)context;
2733 moal_private *priv = handle->priv[handle->cac_bss_index];
2734
2735 PRINTM(MEVENT, "cac_timer fired.\n");
2736 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2737 cfg80211_cac_event(priv->netdev, &handle->dfs_channel,
2738 NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
2739 #else
2740 cfg80211_cac_event(priv->netdev, NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
2741 #endif
2742 handle->is_cac_timer_set = MFALSE;
2743 memset(&handle->dfs_channel, 0, sizeof(struct cfg80211_chan_def));
2744 handle->cac_bss_index = 0xff;
2745 }
2746
2747 /**
2748 * @brief This function switch AP's channel
2749 * 1. clear mgmt IEs 2. stop uAP
2750 * 3. set beacon after 4. set new channel
2751 * 5. start uAP 6. notify cfg80211
2752 *
2753 * @param priv a pointer to moal_private
2754 * @param wait_option wait option
2755 *
2756 * @return N/A
2757 */
2758 void
woal_switch_uap_channel(moal_private * priv,t_u8 wait_option)2759 woal_switch_uap_channel(moal_private *priv, t_u8 wait_option)
2760 {
2761
2762 chan_band_info uap_channel;
2763 t_u8 chan2Offset = SEC_CHAN_NONE;
2764 ENTER();
2765 woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_WAIT);
2766 if (MLAN_STATUS_SUCCESS != woal_uap_bss_ctrl(priv,
2767 wait_option,
2768 UAP_BSS_STOP)) {
2769 PRINTM(MERROR, "%s: stop uap failed \n", __func__);
2770 goto done;
2771 }
2772 if (woal_cfg80211_set_beacon(priv->wdev->wiphy, priv->netdev,
2773 &priv->beacon_after)) {
2774 PRINTM(MERROR, "%s: set mgmt ies failed \n", __func__);
2775 goto done;
2776 }
2777
2778 uap_channel.channel =
2779 ieee80211_frequency_to_channel(priv->csa_chan.chan->
2780 center_freq);
2781 switch (priv->csa_chan.width) {
2782 case NL80211_CHAN_WIDTH_5:
2783 case NL80211_CHAN_WIDTH_10:
2784 case NL80211_CHAN_WIDTH_20_NOHT:
2785 break;
2786 case NL80211_CHAN_WIDTH_20:
2787 break;
2788 case NL80211_CHAN_WIDTH_40:
2789 if (priv->csa_chan.center_freq1 <
2790 priv->csa_chan.chan->center_freq)
2791 chan2Offset = SEC_CHAN_BELOW;
2792 else
2793 chan2Offset = SEC_CHAN_ABOVE;
2794 break;
2795 case NL80211_CHAN_WIDTH_80:
2796 case NL80211_CHAN_WIDTH_80P80:
2797 case NL80211_CHAN_WIDTH_160:
2798 chan2Offset =
2799 woal_get_second_channel_offset(uap_channel.channel);
2800 break;
2801 default:
2802 PRINTM(MWARN, "Unknown channel width: %d\n",
2803 priv->csa_chan.width);
2804 break;
2805 }
2806 if (priv->csa_chan.chan->band == IEEE80211_BAND_2GHZ)
2807 uap_channel.bandcfg.chanBand = BAND_2GHZ;
2808 else if (priv->csa_chan.chan->band == IEEE80211_BAND_5GHZ)
2809 uap_channel.bandcfg.chanBand = BAND_5GHZ;
2810 uap_channel.bandcfg.chan2Offset = chan2Offset;
2811 if (MLAN_STATUS_SUCCESS !=
2812 woal_set_get_ap_channel(priv, MLAN_ACT_SET, wait_option,
2813 &uap_channel)) {
2814 PRINTM(MERROR, "Fail to set ap channel \n");
2815 goto done;
2816 }
2817 if (MLAN_STATUS_SUCCESS !=
2818 woal_uap_bss_ctrl(priv, wait_option, UAP_BSS_START)) {
2819 PRINTM(MERROR, "%s: start uap failed \n", __func__);
2820 goto done;
2821 }
2822 PRINTM(MMSG, "CSA: old chan %d => new chan %d \n", priv->channel,
2823 uap_channel.channel);
2824 priv->channel = uap_channel.channel;
2825 memcpy(&priv->chan, &priv->csa_chan, sizeof(struct cfg80211_chan_def));
2826 cfg80211_ch_switch_notify(priv->netdev, &priv->chan);
2827 if (priv->uap_tx_blocked) {
2828 if (!netif_carrier_ok(priv->netdev))
2829 netif_carrier_on(priv->netdev);
2830 woal_start_queue(priv->netdev);
2831 priv->uap_tx_blocked = MFALSE;
2832 }
2833 done:
2834 LEAVE();
2835 return;
2836 }
2837
2838 /**
2839 * @brief csa work handler
2840 *
2841 * @param work a pointer to work_struct
2842 *
2843 * @return 0 -- success, otherwise fail
2844 */
2845 void
woal_csa_work_queue(struct work_struct * work)2846 woal_csa_work_queue(struct work_struct *work)
2847 {
2848 struct delayed_work *delayed_work =
2849 container_of(work, struct delayed_work, work);
2850 moal_private *priv = container_of(delayed_work, moal_private, csa_work);
2851 ENTER();
2852 if (priv->bss_started == MTRUE)
2853 woal_switch_uap_channel(priv, MOAL_IOCTL_WAIT);
2854 LEAVE();
2855 }
2856
2857 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
2858 /**
2859 * @brief start radar detection
2860 *
2861 * @param wiphy A pointer to wiphy structure
2862 * @param dev A pointer to net_device structure
2863 * @param chandef A pointer to cfg80211_chan_def structure
2864 * @param cac_time_ms A cac dwell time
2865 * @return 0 -- success, otherwise fail
2866 */
2867
2868 int
woal_cfg80211_start_radar_detection(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_chan_def * chandef,u32 cac_time_ms)2869 woal_cfg80211_start_radar_detection(struct wiphy *wiphy,
2870 struct net_device *dev,
2871 struct cfg80211_chan_def *chandef,
2872 u32 cac_time_ms)
2873 #else
2874 /**
2875 * @brief start radar detection
2876 *
2877 * @param wiphy A pointer to wiphy structure
2878 * @param dev A pointer to net_device structure
2879 * @param chandef A pointer to cfg80211_chan_def structure
2880 * @return 0 -- success, otherwise fail
2881 */
2882
2883 int
2884 woal_cfg80211_start_radar_detection(struct wiphy *wiphy,
2885 struct net_device *dev,
2886 struct cfg80211_chan_def *chandef)
2887 #endif
2888 {
2889 moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
2890 moal_handle *handle = priv->phandle;
2891 mlan_ioctl_req *req = NULL;
2892 mlan_ds_11h_chan_rep_req *pchan_rpt_req = NULL;
2893 mlan_ds_11h_cfg *p11h_cfg = NULL;
2894 int ret = 0;
2895 mlan_status status = MLAN_STATUS_SUCCESS;
2896
2897 ENTER();
2898 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
2899 PRINTM(MIOCTL, "start Radar detect, chan %d , Bw %d , Time %d \n",
2900 chandef->chan->hw_value, chandef->width, cac_time_ms);
2901 #else
2902 PRINTM(MIOCTL, "start Radar detect, chan %d , Bw %d \n",
2903 chandef->chan->hw_value, chandef->width);
2904 #endif
2905
2906 if (priv->bss_started == MTRUE) {
2907 PRINTM(MERROR, "recv CAC request when bss already started \n");
2908 ret = -EFAULT;
2909 goto done;
2910 }
2911 if (priv->phandle->cac_period || handle->is_cac_timer_set) {
2912 PRINTM(MERROR,
2913 "Maybe other interface is doing CAC, please defer your oper\n");
2914 ret = -EBUSY;
2915 goto done;
2916 }
2917 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
2918 if (NULL == req) {
2919 ret = -ENOMEM;
2920 goto done;
2921 }
2922
2923 p11h_cfg = (mlan_ds_11h_cfg *)req->pbuf;
2924 pchan_rpt_req = &p11h_cfg->param.chan_rpt_req;
2925 pchan_rpt_req->startFreq = START_FREQ_11A_BAND;
2926 pchan_rpt_req->chanNum = (t_u8)chandef->chan->hw_value;
2927 woal_convert_chan_to_bandconfig(&pchan_rpt_req->bandcfg, chandef);
2928 pchan_rpt_req->host_based = MTRUE;
2929
2930 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
2931 pchan_rpt_req->millisec_dwell_time = cac_time_ms;
2932 #else
2933 pchan_rpt_req->millisec_dwell_time = IEEE80211_DFS_MIN_CAC_TIME_MS;
2934
2935 if ((woal_is_etsi_country(priv->phandle->country_code) == MTRUE)) {
2936 if (chandef->chan->hw_value == 120 ||
2937 chandef->chan->hw_value == 124 ||
2938 chandef->chan->hw_value == 128) {
2939 pchan_rpt_req->millisec_dwell_time =
2940 IEEE80211_DFS_MIN_CAC_TIME_MS * 10;
2941 }
2942 if (chandef->chan->hw_value == 116 &&
2943 ((chandef->width == NL80211_CHAN_WIDTH_40) ||
2944 (chandef->width == NL80211_CHAN_WIDTH_80))) {
2945 pchan_rpt_req->millisec_dwell_time =
2946 IEEE80211_DFS_MIN_CAC_TIME_MS * 10;
2947 }
2948 }
2949 #endif
2950 #if defined(DFS_TESTING_SUPPORT)
2951 if (priv->user_cac_period_msec) {
2952 pchan_rpt_req->millisec_dwell_time = priv->user_cac_period_msec;
2953 PRINTM(MCMD_D,
2954 "cfg80211 dfstesting: User CAC Period=%d (msec) \n",
2955 pchan_rpt_req->millisec_dwell_time);
2956 }
2957 #endif
2958
2959 p11h_cfg->sub_command = MLAN_OID_11H_CHANNEL_CHECK;
2960 req->req_id = MLAN_IOCTL_11H_CFG;
2961 req->action = MLAN_ACT_SET;
2962
2963 /* Send Channel Check command and wait until the report is ready */
2964 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2965 if (status != MLAN_STATUS_SUCCESS) {
2966 PRINTM(MERROR, "Fail to start radar detection\n");
2967 ret = -EFAULT;
2968 } else {
2969 memcpy(&handle->dfs_channel, chandef,
2970 sizeof(struct cfg80211_chan_def));
2971 handle->cac_bss_index = priv->bss_index;
2972 handle->is_cac_timer_set = MTRUE;
2973 /* avoid EVENT_CHANNEL_RAPORT_READY missing, add 1s gap */
2974 woal_mod_timer(&handle->cac_timer,
2975 pchan_rpt_req->millisec_dwell_time + 1000);
2976 }
2977 done:
2978 if (status != MLAN_STATUS_PENDING)
2979 kfree(req);
2980 LEAVE();
2981 return ret;
2982 }
2983
2984 /**
2985 * @brief channel switch
2986
2987 * @param wiphy A pointer to wiphy structure
2988 * @param dev A pointer to net_device structure
2989 * @param params A pointer to cfg80211_csa_settings structure
2990 *
2991 * @return 0 -- success, otherwise fail
2992 */
2993 int
woal_cfg80211_channel_switch(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_csa_settings * params)2994 woal_cfg80211_channel_switch(struct wiphy *wiphy,
2995 struct net_device *dev,
2996 struct cfg80211_csa_settings *params)
2997 {
2998 int ret = 0;
2999 moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
3000 t_u32 chsw_msec;
3001 mlan_uap_bss_param *bss_cfg = NULL;
3002
3003 ENTER();
3004
3005 if (!params) {
3006 ret = -EINVAL;
3007 goto done;
3008 }
3009
3010 /* TODO: support this case in next version */
3011 if (params->radar_required) {
3012 PRINTM(MMSG,
3013 " hostapd handle this case by disable and re-enable interface\n");
3014 ret = -ENOTSUPP;
3015 goto done;
3016 }
3017
3018 /* actually hostapd would always choose one diff channel */
3019 if (cfg80211_chandef_identical(¶ms->chandef, &priv->chan)) {
3020 PRINTM(MMSG,
3021 "csa channel is same with current channel, invaild\n");
3022 ret = -EINVAL;
3023 goto done;
3024 }
3025 bss_cfg = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
3026 if (!bss_cfg) {
3027 PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
3028 ret = -EFAULT;
3029 goto done;
3030 }
3031
3032 if (params->block_tx) {
3033 if (netif_carrier_ok(dev))
3034 netif_carrier_off(dev);
3035 woal_stop_queue(dev);
3036 priv->uap_tx_blocked = MTRUE;
3037 }
3038
3039 woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_WAIT);
3040 if (woal_cfg80211_set_beacon(wiphy, dev, ¶ms->beacon_csa)) {
3041 PRINTM(MERROR, "%s: setting csa mgmt ies failed\n", __func__);
3042 goto done;
3043 }
3044
3045 memcpy(&priv->csa_chan, ¶ms->chandef,
3046 sizeof(struct cfg80211_chan_def));
3047 memcpy(&priv->beacon_after, ¶ms->beacon_after,
3048 sizeof(struct cfg80211_beacon_data));
3049
3050 if (!priv->phandle->fw_ecsa_enable) {
3051 if (MLAN_STATUS_SUCCESS !=
3052 woal_set_get_sys_config(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT,
3053 bss_cfg)) {
3054 PRINTM(MERROR, "%s: get uap config failed\n", __func__);
3055 ret = -EFAULT;
3056 goto done;
3057 }
3058 chsw_msec = params->count * bss_cfg->beacon_period;
3059 queue_delayed_work(priv->csa_workqueue, &priv->csa_work,
3060 msecs_to_jiffies(chsw_msec));
3061 }
3062 done:
3063 kfree(bss_cfg);
3064 LEAVE();
3065 return ret;
3066 }
3067 #endif
3068
3069 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
3070 /**
3071 * @brief Notify cfg80211 uap channel changed
3072 *
3073 * @param priv A pointer moal_private structure
3074 * @param pchan_info A pointer to chan_band structure
3075 *
3076 * @return N/A
3077 */
3078 void
woal_cfg80211_notify_uap_channel(moal_private * priv,chan_band_info * pchan_info)3079 woal_cfg80211_notify_uap_channel(moal_private *priv,
3080 chan_band_info * pchan_info)
3081 {
3082 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
3083 struct cfg80211_chan_def chandef;
3084 #else
3085 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
3086 enum nl80211_channel_type type;
3087 enum ieee80211_band band;
3088 int freq = 0;
3089 #endif
3090 #endif
3091 ENTER();
3092
3093 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
3094 if (MLAN_STATUS_SUCCESS ==
3095 woal_chandef_create(priv, &chandef, pchan_info))
3096 cfg80211_ch_switch_notify(priv->netdev, &chandef);
3097 #else
3098 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
3099 if (pchan_info->bandcfg.chanBand == BAND_2GHZ)
3100 band = IEEE80211_BAND_2GHZ;
3101 else if (pchan_info->bandcfg.chanBand == BAND_5GHZ)
3102 band = IEEE80211_BAND_5GHZ;
3103 else {
3104 LEAVE();
3105 return;
3106 }
3107 freq = ieee80211_channel_to_frequency(pchan_info->channel, band);
3108 switch (pchan_info->bandcfg.chanWidth) {
3109 case CHAN_BW_20MHZ:
3110 if (pchan_info->is_11n_enabled)
3111 type = NL80211_CHAN_HT20;
3112 else
3113 type = NL80211_CHAN_NO_HT;
3114 break;
3115 default:
3116 if (pchan_info->bandcfg.chan2Offset == SEC_CHAN_ABOVE)
3117 type = NL80211_CHAN_HT40PLUS;
3118 else if (pchan_info->bandcfg.chan2Offset == SEC_CHAN_BELOW)
3119 type = NL80211_CHAN_HT40MINUS;
3120 else
3121 type = NL80211_CHAN_HT20;
3122 break;
3123 }
3124 cfg80211_ch_switch_notify(priv->netdev, freq, type);
3125 #endif
3126 #endif
3127 LEAVE();
3128 }
3129 #endif
3130
3131 /**
3132 * @brief Register the device with cfg80211
3133 *
3134 * @param dev A pointer to net_device structure
3135 * @param bss_type BSS type
3136 *
3137 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3138 */
3139 mlan_status
woal_register_uap_cfg80211(struct net_device * dev,t_u8 bss_type)3140 woal_register_uap_cfg80211(struct net_device *dev, t_u8 bss_type)
3141 {
3142 mlan_status ret = MLAN_STATUS_SUCCESS;
3143 moal_private *priv = (moal_private *)netdev_priv(dev);
3144 struct wireless_dev *wdev = NULL;
3145
3146 ENTER();
3147
3148 wdev = (struct wireless_dev *)&priv->w_dev;
3149 memset(wdev, 0, sizeof(struct wireless_dev));
3150
3151 wdev->wiphy = priv->phandle->wiphy;
3152 if (!wdev->wiphy) {
3153 LEAVE();
3154 return MLAN_STATUS_FAILURE;
3155 }
3156
3157 if (bss_type == MLAN_BSS_TYPE_UAP)
3158 wdev->iftype = NL80211_IFTYPE_AP;
3159
3160 dev_net_set(dev, wiphy_net(wdev->wiphy));
3161 dev->ieee80211_ptr = wdev;
3162 SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy));
3163 priv->wdev = wdev;
3164
3165 LEAVE();
3166 return ret;
3167 }
3168