staging: rtl8723bs: Fix key-store index handling
[platform/kernel/linux-rpi.git] / drivers / staging / rtl8723bs / os_dep / ioctl_linux.c
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7
8 #include <linux/etherdevice.h>
9 #include <drv_types.h>
10 #include <rtw_debug.h>
11 #include <rtw_mp.h>
12 #include <hal_btcoex.h>
13 #include <linux/jiffies.h>
14 #include <linux/kernel.h>
15
16 #define RTL_IOCTL_WPA_SUPPLICANT        (SIOCIWFIRSTPRIV+30)
17
18 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
19 {
20         struct adapter *padapter = rtw_netdev_priv(dev);
21         int ret = 0;
22
23         if ((value & IW_AUTH_ALG_SHARED_KEY) && (value & IW_AUTH_ALG_OPEN_SYSTEM)) {
24                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
25                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
26                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
27         } else if (value & IW_AUTH_ALG_SHARED_KEY)      {
28                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
29
30                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
31                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
32         } else if (value & IW_AUTH_ALG_OPEN_SYSTEM) {
33                 /* padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; */
34                 if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
35                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
36                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
37                 }
38         } else {
39                 ret = -EINVAL;
40         }
41
42         return ret;
43
44 }
45
46 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
47 {
48         int ret = 0;
49         u8 max_idx;
50         u32 wep_key_idx, wep_key_len, wep_total_len;
51         struct ndis_802_11_wep   *pwep = NULL;
52         struct adapter *padapter = rtw_netdev_priv(dev);
53         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
54         struct security_priv *psecuritypriv = &padapter->securitypriv;
55
56         param->u.crypt.err = 0;
57         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
58
59         if (param_len < (u32)((u8 *)param->u.crypt.key - (u8 *)param) + param->u.crypt.key_len) {
60                 ret =  -EINVAL;
61                 goto exit;
62         }
63
64         if (param->sta_addr[0] != 0xff || param->sta_addr[1] != 0xff ||
65             param->sta_addr[2] != 0xff || param->sta_addr[3] != 0xff ||
66             param->sta_addr[4] != 0xff || param->sta_addr[5] != 0xff) {
67                 ret = -EINVAL;
68                 goto exit;
69         }
70
71         if (strcmp(param->u.crypt.alg, "WEP") == 0)
72                 max_idx = WEP_KEYS - 1;
73         else
74                 max_idx = BIP_MAX_KEYID;
75
76         if (param->u.crypt.idx > max_idx) {
77                 netdev_err(dev, "Error crypt.idx %d > %d\n", param->u.crypt.idx, max_idx);
78                 ret = -EINVAL;
79                 goto exit;
80         }
81
82         if (strcmp(param->u.crypt.alg, "WEP") == 0) {
83
84                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
85                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
86                 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
87
88                 wep_key_idx = param->u.crypt.idx;
89                 wep_key_len = param->u.crypt.key_len;
90
91                 if (wep_key_len > 0) {
92                         wep_key_len = wep_key_len <= 5 ? 5 : 13;
93                         wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, key_material);
94                         /* Allocate a full structure to avoid potentially running off the end. */
95                         pwep = kzalloc(sizeof(*pwep), GFP_KERNEL);
96                         if (!pwep) {
97                                 ret = -ENOMEM;
98                                 goto exit;
99                         }
100
101                         pwep->key_length = wep_key_len;
102                         pwep->length = wep_total_len;
103
104                         if (wep_key_len == 13) {
105                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
106                                 padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
107                         }
108                 } else {
109                         ret = -EINVAL;
110                         goto exit;
111                 }
112
113                 pwep->key_index = wep_key_idx;
114                 pwep->key_index |= 0x80000000;
115
116                 memcpy(pwep->key_material,  param->u.crypt.key, pwep->key_length);
117
118                 if (param->u.crypt.set_tx) {
119                         if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
120                                 ret = -EOPNOTSUPP;
121                 } else {
122                         /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
123                         /* psecuritypriv->dot11PrivacyKeyIndex =keyid", but can rtw_set_key to fw/cam */
124
125                         if (wep_key_idx >= WEP_KEYS) {
126                                 ret = -EOPNOTSUPP;
127                                 goto exit;
128                         }
129
130                         memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->key_material, pwep->key_length);
131                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->key_length;
132                         rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0, true);
133                 }
134
135                 goto exit;
136         }
137
138         if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /*  802_1x */
139                 struct sta_info *psta, *pbcmc_sta;
140                 struct sta_priv *pstapriv = &padapter->stapriv;
141
142                 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == true) { /* sta mode */
143                         psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
144                         if (!psta) {
145                                 /* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
146                         } else {
147                                 /* Jeff: don't disable ieee8021x_blocked while clearing key */
148                                 if (strcmp(param->u.crypt.alg, "none") != 0)
149                                         psta->ieee8021x_blocked = false;
150
151                                 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
152                                                 (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled)) {
153                                         psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
154                                 }
155
156                                 if (param->u.crypt.set_tx == 1) { /* pairwise key */
157                                         memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
158
159                                         if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
160                                                 /* DEBUG_ERR(("\nset key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */
161                                                 memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
162                                                 memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
163
164                                                 padapter->securitypriv.busetkipkey = false;
165                                                 /* _set_timer(&padapter->securitypriv.tkip_timer, 50); */
166                                         }
167
168                                         rtw_setstakey_cmd(padapter, psta, true, true);
169                                 } else { /* group key */
170                                         if (strcmp(param->u.crypt.alg, "TKIP") == 0 || strcmp(param->u.crypt.alg, "CCMP") == 0) {
171                                                 memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
172                                                 /* only TKIP group key need to install this */
173                                                 if (param->u.crypt.key_len > 16) {
174                                                         memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
175                                                         memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
176                                                 }
177                                                 padapter->securitypriv.binstallGrpkey = true;
178
179                                                 padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
180
181                                                 rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1, true);
182                                         } else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
183                                                 /* printk("BIP key_len =%d , index =%d @@@@@@@@@@@@@@@@@@\n", param->u.crypt.key_len, param->u.crypt.idx); */
184                                                 /* save the IGTK key, length 16 bytes */
185                                                 memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
186                                                 /*printk("IGTK key below:\n");
187                                                 for (no = 0;no<16;no++)
188                                                         printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]);
189                                                 printk("\n");*/
190                                                 padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
191                                                 padapter->securitypriv.binstallBIPkey = true;
192                                         }
193                                 }
194                         }
195
196                         pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
197                         if (!pbcmc_sta) {
198                                 /* DEBUG_ERR(("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */
199                         } else {
200                                 /* Jeff: don't disable ieee8021x_blocked while clearing key */
201                                 if (strcmp(param->u.crypt.alg, "none") != 0)
202                                         pbcmc_sta->ieee8021x_blocked = false;
203
204                                 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
205                                                 (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled)) {
206                                         pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
207                                 }
208                         }
209                 } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
210                         /* adhoc mode */
211                 }
212         }
213
214 exit:
215
216         kfree(pwep);
217         return ret;
218 }
219
220 static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ielen)
221 {
222         u8 *buf = NULL;
223         int group_cipher = 0, pairwise_cipher = 0;
224         int ret = 0;
225         u8 null_addr[] = {0, 0, 0, 0, 0, 0};
226
227         if (ielen > MAX_WPA_IE_LEN || !pie) {
228                 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
229                 if (!pie)
230                         return ret;
231                 else
232                         return -EINVAL;
233         }
234
235         if (ielen) {
236                 buf = rtw_zmalloc(ielen);
237                 if (!buf) {
238                         ret =  -ENOMEM;
239                         goto exit;
240                 }
241
242                 memcpy(buf, pie, ielen);
243
244                 if (ielen < RSN_HEADER_LEN) {
245                         ret  = -1;
246                         goto exit;
247                 }
248
249                 if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
250                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
251                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
252                         memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
253                 }
254
255                 if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
256                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
257                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
258                         memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
259                 }
260
261                 if (group_cipher == 0)
262                         group_cipher = WPA_CIPHER_NONE;
263                 if (pairwise_cipher == 0)
264                         pairwise_cipher = WPA_CIPHER_NONE;
265
266                 switch (group_cipher) {
267                 case WPA_CIPHER_NONE:
268                         padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
269                         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
270                         break;
271                 case WPA_CIPHER_WEP40:
272                         padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
273                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
274                         break;
275                 case WPA_CIPHER_TKIP:
276                         padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
277                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
278                         break;
279                 case WPA_CIPHER_CCMP:
280                         padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
281                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
282                         break;
283                 case WPA_CIPHER_WEP104:
284                         padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
285                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
286                         break;
287                 }
288
289                 switch (pairwise_cipher) {
290                 case WPA_CIPHER_NONE:
291                         padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
292                         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
293                         break;
294                 case WPA_CIPHER_WEP40:
295                         padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
296                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
297                         break;
298                 case WPA_CIPHER_TKIP:
299                         padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
300                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
301                         break;
302                 case WPA_CIPHER_CCMP:
303                         padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
304                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
305                         break;
306                 case WPA_CIPHER_WEP104:
307                         padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
308                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
309                         break;
310                 }
311
312                 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
313                 {/* set wps_ie */
314                         u16 cnt = 0;
315                         u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
316
317                         while (cnt < ielen) {
318                                 eid = buf[cnt];
319
320                                 if ((eid == WLAN_EID_VENDOR_SPECIFIC) && (!memcmp(&buf[cnt+2], wps_oui, 4))) {
321                                         padapter->securitypriv.wps_ie_len = ((buf[cnt+1]+2) < MAX_WPS_IE_LEN) ? (buf[cnt+1]+2):MAX_WPS_IE_LEN;
322
323                                         memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
324
325                                         set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
326
327                                         cnt += buf[cnt+1]+2;
328
329                                         break;
330                                 } else {
331                                         cnt += buf[cnt+1]+2; /* goto next */
332                                 }
333                         }
334                 }
335         }
336
337         /* TKIP and AES disallow multicast packets until installing group key */
338         if (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_ ||
339                 padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_ ||
340                 padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
341                 /* WPS open need to enable multicast */
342                 /*  check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true) */
343                 rtw_hal_set_hwreg(padapter, HW_VAR_OFF_RCR_AM, null_addr);
344
345 exit:
346
347         kfree(buf);
348
349         return ret;
350 }
351
352 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
353 {
354         uint ret = 0;
355         struct adapter *padapter = rtw_netdev_priv(dev);
356
357         switch (name) {
358         case IEEE_PARAM_WPA_ENABLED:
359
360                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */
361
362                 /* ret = ieee80211_wpa_enable(ieee, value); */
363
364                 switch ((value)&0xff) {
365                 case 1: /* WPA */
366                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
367                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
368                         break;
369                 case 2: /* WPA2 */
370                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
371                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
372                         break;
373                 }
374
375                 break;
376
377         case IEEE_PARAM_TKIP_COUNTERMEASURES:
378                 /* ieee->tkip_countermeasures =value; */
379                 break;
380
381         case IEEE_PARAM_DROP_UNENCRYPTED:
382         {
383                 /* HACK:
384                  *
385                  * wpa_supplicant calls set_wpa_enabled when the driver
386                  * is loaded and unloaded, regardless of if WPA is being
387                  * used.  No other calls are made which can be used to
388                  * determine if encryption will be used or not prior to
389                  * association being expected.  If encryption is not being
390                  * used, drop_unencrypted is set to false, else true -- we
391                  * can use this to determine if the CAP_PRIVACY_ON bit should
392                  * be set.
393                  */
394                 break;
395
396         }
397         case IEEE_PARAM_PRIVACY_INVOKED:
398
399                 /* ieee->privacy_invoked =value; */
400
401                 break;
402
403         case IEEE_PARAM_AUTH_ALGS:
404
405                 ret = wpa_set_auth_algs(dev, value);
406
407                 break;
408
409         case IEEE_PARAM_IEEE_802_1X:
410
411                 /* ieee->ieee802_1x =value; */
412
413                 break;
414
415         case IEEE_PARAM_WPAX_SELECT:
416
417                 /*  added for WPA2 mixed mode */
418                 /*
419                 spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags);
420                 ieee->wpax_type_set = 1;
421                 ieee->wpax_type_notify = value;
422                 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags);
423                 */
424
425                 break;
426
427         default:
428
429
430
431                 ret = -EOPNOTSUPP;
432
433
434                 break;
435
436         }
437
438         return ret;
439
440 }
441
442 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
443 {
444         int ret = 0;
445         struct adapter *padapter = rtw_netdev_priv(dev);
446
447         switch (command) {
448         case IEEE_MLME_STA_DEAUTH:
449
450                 if (!rtw_set_802_11_disassociate(padapter))
451                         ret = -1;
452
453                 break;
454
455         case IEEE_MLME_STA_DISASSOC:
456
457                 if (!rtw_set_802_11_disassociate(padapter))
458                         ret = -1;
459
460                 break;
461
462         default:
463                 ret = -EOPNOTSUPP;
464                 break;
465         }
466
467         return ret;
468
469 }
470
471 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
472 {
473         struct ieee_param *param;
474         uint ret = 0;
475
476         /* down(&ieee->wx_sem); */
477
478         if (!p->pointer || p->length != sizeof(struct ieee_param))
479                 return -EINVAL;
480
481         param = rtw_malloc(p->length);
482         if (!param)
483                 return -ENOMEM;
484
485         if (copy_from_user(param, p->pointer, p->length)) {
486                 kfree(param);
487                 return -EFAULT;
488         }
489
490         switch (param->cmd) {
491
492         case IEEE_CMD_SET_WPA_PARAM:
493                 ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
494                 break;
495
496         case IEEE_CMD_SET_WPA_IE:
497                 /* ret = wpa_set_wpa_ie(dev, param, p->length); */
498                 ret =  rtw_set_wpa_ie(rtw_netdev_priv(dev), (char *)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
499                 break;
500
501         case IEEE_CMD_SET_ENCRYPTION:
502                 ret = wpa_set_encryption(dev, param, p->length);
503                 break;
504
505         case IEEE_CMD_MLME:
506                 ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
507                 break;
508
509         default:
510                 ret = -EOPNOTSUPP;
511                 break;
512
513         }
514
515         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
516                 ret = -EFAULT;
517
518         kfree(param);
519
520         /* up(&ieee->wx_sem); */
521         return ret;
522 }
523
524 static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
525 {
526         int ret = 0;
527         u32 wep_key_idx, wep_key_len, wep_total_len;
528         struct ndis_802_11_wep   *pwep = NULL;
529         struct sta_info *psta = NULL, *pbcmc_sta = NULL;
530         struct adapter *padapter = rtw_netdev_priv(dev);
531         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
532         struct security_priv *psecuritypriv = &(padapter->securitypriv);
533         struct sta_priv *pstapriv = &padapter->stapriv;
534         char *txkey = padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey;
535         char *rxkey = padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey;
536         char *grpkey = psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey;
537
538         param->u.crypt.err = 0;
539         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
540
541         /* sizeof(struct ieee_param) = 64 bytes; */
542         /* if (param_len !=  (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) */
543         if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {
544                 ret =  -EINVAL;
545                 goto exit;
546         }
547
548         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
549             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
550             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
551                 if (param->u.crypt.idx >= WEP_KEYS) {
552                         ret = -EINVAL;
553                         goto exit;
554                 }
555         } else {
556                 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
557                 if (!psta)
558                         /* ret = -EINVAL; */
559                         goto exit;
560         }
561
562         if (strcmp(param->u.crypt.alg, "none") == 0 && !psta) {
563                 /* todo:clear default encryption keys */
564
565                 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
566                 psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
567                 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
568                 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
569
570                 goto exit;
571         }
572
573
574         if (strcmp(param->u.crypt.alg, "WEP") == 0 && !psta) {
575                 wep_key_idx = param->u.crypt.idx;
576                 wep_key_len = param->u.crypt.key_len;
577
578                 if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
579                         ret = -EINVAL;
580                         goto exit;
581                 }
582
583
584                 if (wep_key_len > 0) {
585                         wep_key_len = wep_key_len <= 5 ? 5 : 13;
586                         wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, key_material);
587                         /* Allocate a full structure to avoid potentially running off the end. */
588                         pwep = kzalloc(sizeof(*pwep), GFP_KERNEL);
589                         if (!pwep)
590                                 goto exit;
591
592                         pwep->key_length = wep_key_len;
593                         pwep->length = wep_total_len;
594
595                 }
596
597                 pwep->key_index = wep_key_idx;
598
599                 memcpy(pwep->key_material,  param->u.crypt.key, pwep->key_length);
600
601                 if (param->u.crypt.set_tx) {
602                         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
603                         psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
604                         psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
605                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
606
607                         if (pwep->key_length == 13) {
608                                 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
609                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
610                         }
611
612
613                         psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
614
615                         memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->key_material, pwep->key_length);
616
617                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->key_length;
618
619                         rtw_ap_set_wep_key(padapter, pwep->key_material, pwep->key_length, wep_key_idx, 1);
620                 } else {
621                         /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
622                         /* psecuritypriv->dot11PrivacyKeyIndex =keyid", but can rtw_set_key to cam */
623
624                         memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->key_material, pwep->key_length);
625
626                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->key_length;
627
628                         rtw_ap_set_wep_key(padapter, pwep->key_material, pwep->key_length, wep_key_idx, 0);
629                 }
630
631                 goto exit;
632
633         }
634
635
636         if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /*  group key */
637                 if (param->u.crypt.set_tx == 1) {
638                         if (strcmp(param->u.crypt.alg, "WEP") == 0) {
639                                 memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
640
641                                 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
642                                 if (param->u.crypt.key_len == 13)
643                                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
644
645                         } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
646                                 psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
647
648                                 memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
649
650                                 /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
651                                 /* set mic key */
652                                 memcpy(txkey, &(param->u.crypt.key[16]), 8);
653                                 memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
654
655                                 psecuritypriv->busetkipkey = true;
656
657                         }
658                         else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
659                                 psecuritypriv->dot118021XGrpPrivacy = _AES_;
660
661                                 memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
662                         } else {
663                                 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
664                         }
665
666                         psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
667
668                         psecuritypriv->binstallGrpkey = true;
669
670                         psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
671
672                         rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
673
674                         pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
675                         if (pbcmc_sta) {
676                                 pbcmc_sta->ieee8021x_blocked = false;
677                                 pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
678                         }
679                 }
680
681                 goto exit;
682
683         }
684
685         if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /*  psk/802_1x */
686                 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
687                         if (param->u.crypt.set_tx == 1) {
688                                 memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
689
690                                 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
691                                         psta->dot118021XPrivacy = _WEP40_;
692                                         if (param->u.crypt.key_len == 13)
693                                                 psta->dot118021XPrivacy = _WEP104_;
694                                 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
695                                         psta->dot118021XPrivacy = _TKIP_;
696
697                                         /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
698                                         /* set mic key */
699                                         memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
700                                         memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
701
702                                         psecuritypriv->busetkipkey = true;
703
704                                 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
705
706                                         psta->dot118021XPrivacy = _AES_;
707                                 } else {
708                                         psta->dot118021XPrivacy = _NO_PRIVACY_;
709                                 }
710
711                                 rtw_ap_set_pairwise_key(padapter, psta);
712
713                                 psta->ieee8021x_blocked = false;
714
715                         } else { /* group key??? */
716                                 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
717                                         memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
718
719                                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
720                                         if (param->u.crypt.key_len == 13)
721                                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
722                                 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
723                                         psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
724
725                                         memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
726
727                                         /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
728                                         /* set mic key */
729                                         memcpy(txkey, &(param->u.crypt.key[16]), 8);
730                                         memcpy(rxkey, &(param->u.crypt.key[24]), 8);
731
732                                         psecuritypriv->busetkipkey = true;
733
734                                 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
735                                         psecuritypriv->dot118021XGrpPrivacy = _AES_;
736
737                                         memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
738                                 } else {
739                                         psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
740                                 }
741
742                                 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
743
744                                 psecuritypriv->binstallGrpkey = true;
745
746                                 psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
747
748                                 rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
749
750                                 pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
751                                 if (pbcmc_sta) {
752                                         pbcmc_sta->ieee8021x_blocked = false;
753                                         pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
754                                 }
755                         }
756                 }
757         }
758
759 exit:
760         kfree(pwep);
761
762         return ret;
763
764 }
765
766 static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
767 {
768         int ret = 0;
769         struct adapter *padapter = rtw_netdev_priv(dev);
770         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
771         struct sta_priv *pstapriv = &padapter->stapriv;
772         unsigned char *pbuf = param->u.bcn_ie.buf;
773
774         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
775                 return -EINVAL;
776
777         memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
778
779         if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
780                 pstapriv->max_num_sta = NUM_STA;
781
782
783         if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) == _SUCCESS)/*  12 = param header, 2:no packed */
784                 ret = 0;
785         else
786                 ret = -EINVAL;
787
788
789         return ret;
790
791 }
792
793 static void rtw_hostapd_sta_flush(struct net_device *dev)
794 {
795         /* _irqL irqL; */
796         /* struct list_head     *phead, *plist; */
797         /* struct sta_info *psta = NULL; */
798         struct adapter *padapter = rtw_netdev_priv(dev);
799         /* struct sta_priv *pstapriv = &padapter->stapriv; */
800
801         flush_all_cam_entry(padapter);  /* clear CAM */
802
803         rtw_sta_flush(padapter);
804 }
805
806 static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
807 {
808         int ret = 0;
809         struct sta_info *psta = NULL;
810         struct adapter *padapter = rtw_netdev_priv(dev);
811         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
812         struct sta_priv *pstapriv = &padapter->stapriv;
813
814         if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
815                 return -EINVAL;
816
817         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
818             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
819             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
820                 return -EINVAL;
821         }
822
823 /*
824         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
825         if (psta)
826         {
827                 rtw_free_stainfo(padapter,  psta);
828
829                 psta = NULL;
830         }
831 */
832         /* psta = rtw_alloc_stainfo(pstapriv, param->sta_addr); */
833         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
834         if (psta) {
835                 int flags = param->u.add_sta.flags;
836
837                 psta->aid = param->u.add_sta.aid;/* aid = 1~2007 */
838
839                 memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
840
841
842                 /* check wmm cap. */
843                 if (WLAN_STA_WME&flags)
844                         psta->qos_option = 1;
845                 else
846                         psta->qos_option = 0;
847
848                 if (pmlmepriv->qospriv.qos_option == 0)
849                         psta->qos_option = 0;
850
851                 /* chec 802.11n ht cap. */
852                 if (WLAN_STA_HT&flags) {
853                         psta->htpriv.ht_option = true;
854                         psta->qos_option = 1;
855                         memcpy((void *)&psta->htpriv.ht_cap, (void *)&param->u.add_sta.ht_cap, sizeof(struct ieee80211_ht_cap));
856                 } else {
857                         psta->htpriv.ht_option = false;
858                 }
859
860                 if (pmlmepriv->htpriv.ht_option == false)
861                         psta->htpriv.ht_option = false;
862
863                 update_sta_info_apmode(padapter, psta);
864
865
866         } else {
867                 ret = -ENOMEM;
868         }
869
870         return ret;
871
872 }
873
874 static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
875 {
876         int ret = 0;
877         struct sta_info *psta = NULL;
878         struct adapter *padapter = rtw_netdev_priv(dev);
879         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
880         struct sta_priv *pstapriv = &padapter->stapriv;
881
882         if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
883                 return -EINVAL;
884
885         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
886             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
887             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
888                 return -EINVAL;
889         }
890
891         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
892         if (psta) {
893                 u8 updated = false;
894
895                 spin_lock_bh(&pstapriv->asoc_list_lock);
896                 if (list_empty(&psta->asoc_list) == false) {
897                         list_del_init(&psta->asoc_list);
898                         pstapriv->asoc_list_cnt--;
899                         updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
900
901                 }
902                 spin_unlock_bh(&pstapriv->asoc_list_lock);
903
904                 associated_clients_update(padapter, updated);
905
906                 psta = NULL;
907
908         }
909
910         return ret;
911
912 }
913
914 static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
915 {
916         int ret = 0;
917         struct sta_info *psta = NULL;
918         struct adapter *padapter = rtw_netdev_priv(dev);
919         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
920         struct sta_priv *pstapriv = &padapter->stapriv;
921         struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
922         struct sta_data *psta_data = (struct sta_data *)param_ex->data;
923
924         if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
925                 return -EINVAL;
926
927         if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
928             param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
929             param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff) {
930                 return -EINVAL;
931         }
932
933         psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
934         if (psta) {
935                 psta_data->aid = (u16)psta->aid;
936                 psta_data->capability = psta->capability;
937                 psta_data->flags = psta->flags;
938
939 /*
940                 nonerp_set : BIT(0)
941                 no_short_slot_time_set : BIT(1)
942                 no_short_preamble_set : BIT(2)
943                 no_ht_gf_set : BIT(3)
944                 no_ht_set : BIT(4)
945                 ht_20mhz_set : BIT(5)
946 */
947
948                 psta_data->sta_set = ((psta->nonerp_set) |
949                                                          (psta->no_short_slot_time_set << 1) |
950                                                          (psta->no_short_preamble_set << 2) |
951                                                          (psta->no_ht_gf_set << 3) |
952                                                          (psta->no_ht_set << 4) |
953                                                          (psta->ht_20mhz_set << 5));
954
955                 psta_data->tx_supp_rates_len =  psta->bssratelen;
956                 memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
957                 memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct ieee80211_ht_cap));
958                 psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
959                 psta_data->rx_bytes = psta->sta_stats.rx_bytes;
960                 psta_data->rx_drops = psta->sta_stats.rx_drops;
961
962                 psta_data->tx_pkts = psta->sta_stats.tx_pkts;
963                 psta_data->tx_bytes = psta->sta_stats.tx_bytes;
964                 psta_data->tx_drops = psta->sta_stats.tx_drops;
965
966
967         } else {
968                 ret = -1;
969         }
970
971         return ret;
972
973 }
974
975 static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
976 {
977         int ret = 0;
978         struct sta_info *psta = NULL;
979         struct adapter *padapter = rtw_netdev_priv(dev);
980         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
981         struct sta_priv *pstapriv = &padapter->stapriv;
982
983         if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
984                 return -EINVAL;
985
986         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
987             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
988             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
989                 return -EINVAL;
990         }
991
992         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
993         if (psta) {
994                 if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC)) {
995                         int wpa_ie_len;
996                         int copy_len;
997
998                         wpa_ie_len = psta->wpa_ie[1];
999
1000                         copy_len = ((wpa_ie_len+2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)):(wpa_ie_len+2);
1001
1002                         param->u.wpa_ie.len = copy_len;
1003
1004                         memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
1005                 }
1006         } else {
1007                 ret = -1;
1008         }
1009
1010         return ret;
1011
1012 }
1013
1014 static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
1015 {
1016         int ret = 0;
1017         unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
1018         struct adapter *padapter = rtw_netdev_priv(dev);
1019         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1020         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1021         int ie_len;
1022
1023         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
1024                 return -EINVAL;
1025
1026         ie_len = len-12-2;/*  12 = param header, 2:no packed */
1027
1028
1029         kfree(pmlmepriv->wps_beacon_ie);
1030         pmlmepriv->wps_beacon_ie = NULL;
1031
1032         if (ie_len > 0) {
1033                 pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
1034                 pmlmepriv->wps_beacon_ie_len = ie_len;
1035                 if (!pmlmepriv->wps_beacon_ie)
1036                         return -EINVAL;
1037
1038                 memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
1039
1040                 update_beacon(padapter, WLAN_EID_VENDOR_SPECIFIC, wps_oui, true);
1041
1042                 pmlmeext->bstart_bss = true;
1043         }
1044
1045
1046         return ret;
1047
1048 }
1049
1050 static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
1051 {
1052         int ret = 0;
1053         struct adapter *padapter = rtw_netdev_priv(dev);
1054         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1055         int ie_len;
1056
1057         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
1058                 return -EINVAL;
1059
1060         ie_len = len-12-2;/*  12 = param header, 2:no packed */
1061
1062
1063         kfree(pmlmepriv->wps_probe_resp_ie);
1064         pmlmepriv->wps_probe_resp_ie = NULL;
1065
1066         if (ie_len > 0) {
1067                 pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
1068                 pmlmepriv->wps_probe_resp_ie_len = ie_len;
1069                 if (!pmlmepriv->wps_probe_resp_ie)
1070                         return -EINVAL;
1071
1072                 memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
1073         }
1074
1075
1076         return ret;
1077
1078 }
1079
1080 static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
1081 {
1082         int ret = 0;
1083         struct adapter *padapter = rtw_netdev_priv(dev);
1084         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1085         int ie_len;
1086
1087         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
1088                 return -EINVAL;
1089
1090         ie_len = len-12-2;/*  12 = param header, 2:no packed */
1091
1092
1093         kfree(pmlmepriv->wps_assoc_resp_ie);
1094         pmlmepriv->wps_assoc_resp_ie = NULL;
1095
1096         if (ie_len > 0) {
1097                 pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
1098                 pmlmepriv->wps_assoc_resp_ie_len = ie_len;
1099                 if (!pmlmepriv->wps_assoc_resp_ie)
1100                         return -EINVAL;
1101
1102                 memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
1103         }
1104
1105
1106         return ret;
1107
1108 }
1109
1110 static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
1111 {
1112         int ret = 0;
1113         struct adapter *adapter = rtw_netdev_priv(dev);
1114         struct mlme_priv *mlmepriv = &(adapter->mlmepriv);
1115         struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
1116         struct mlme_ext_info *mlmeinfo = &(mlmeext->mlmext_info);
1117         int ie_len;
1118         u8 *ssid_ie;
1119         char ssid[NDIS_802_11_LENGTH_SSID + 1];
1120         signed int ssid_len;
1121         u8 ignore_broadcast_ssid;
1122
1123         if (check_fwstate(mlmepriv, WIFI_AP_STATE) != true)
1124                 return -EPERM;
1125
1126         if (param->u.bcn_ie.reserved[0] != 0xea)
1127                 return -EINVAL;
1128
1129         mlmeinfo->hidden_ssid_mode = ignore_broadcast_ssid = param->u.bcn_ie.reserved[1];
1130
1131         ie_len = len-12-2;/*  12 = param header, 2:no packed */
1132         ssid_ie = rtw_get_ie(param->u.bcn_ie.buf,  WLAN_EID_SSID, &ssid_len, ie_len);
1133
1134         if (ssid_ie && ssid_len > 0 && ssid_len <= NDIS_802_11_LENGTH_SSID) {
1135                 struct wlan_bssid_ex *pbss_network = &mlmepriv->cur_network.network;
1136                 struct wlan_bssid_ex *pbss_network_ext = &mlmeinfo->network;
1137
1138                 memcpy(ssid, ssid_ie+2, ssid_len);
1139                 ssid[ssid_len] = 0x0;
1140
1141                 memcpy(pbss_network->ssid.ssid, (void *)ssid, ssid_len);
1142                 pbss_network->ssid.ssid_length = ssid_len;
1143                 memcpy(pbss_network_ext->ssid.ssid, (void *)ssid, ssid_len);
1144                 pbss_network_ext->ssid.ssid_length = ssid_len;
1145         }
1146
1147         return ret;
1148 }
1149
1150 static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
1151 {
1152         struct adapter *padapter = rtw_netdev_priv(dev);
1153         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1154
1155         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
1156                 return -EINVAL;
1157
1158         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
1159             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
1160             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
1161                 return -EINVAL;
1162         }
1163
1164         rtw_acl_remove_sta(padapter, param->sta_addr);
1165         return 0;
1166
1167 }
1168
1169 static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
1170 {
1171         struct adapter *padapter = rtw_netdev_priv(dev);
1172         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1173
1174         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
1175                 return -EINVAL;
1176
1177         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
1178             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
1179             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
1180                 return -EINVAL;
1181         }
1182
1183         return rtw_acl_add_sta(padapter, param->sta_addr);
1184
1185 }
1186
1187 static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
1188 {
1189         int ret = 0;
1190         struct adapter *padapter = rtw_netdev_priv(dev);
1191         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1192
1193         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
1194                 return -EINVAL;
1195
1196         rtw_set_macaddr_acl(padapter, param->u.mlme.command);
1197
1198         return ret;
1199 }
1200
1201 static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
1202 {
1203         struct ieee_param *param;
1204         int ret = 0;
1205         struct adapter *padapter = rtw_netdev_priv(dev);
1206
1207         /*
1208         * this function is expect to call in master mode, which allows no power saving
1209         * so, we just check hw_init_completed
1210         */
1211
1212         if (!padapter->hw_init_completed)
1213                 return -EPERM;
1214
1215         if (!p->pointer || p->length != sizeof(*param))
1216                 return -EINVAL;
1217
1218         param = rtw_malloc(p->length);
1219         if (!param)
1220                 return -ENOMEM;
1221
1222         if (copy_from_user(param, p->pointer, p->length)) {
1223                 kfree(param);
1224                 return -EFAULT;
1225         }
1226
1227         switch (param->cmd) {
1228         case RTL871X_HOSTAPD_FLUSH:
1229
1230                 rtw_hostapd_sta_flush(dev);
1231
1232                 break;
1233
1234         case RTL871X_HOSTAPD_ADD_STA:
1235
1236                 ret = rtw_add_sta(dev, param);
1237
1238                 break;
1239
1240         case RTL871X_HOSTAPD_REMOVE_STA:
1241
1242                 ret = rtw_del_sta(dev, param);
1243
1244                 break;
1245
1246         case RTL871X_HOSTAPD_SET_BEACON:
1247
1248                 ret = rtw_set_beacon(dev, param, p->length);
1249
1250                 break;
1251
1252         case RTL871X_SET_ENCRYPTION:
1253
1254                 ret = rtw_set_encryption(dev, param, p->length);
1255
1256                 break;
1257
1258         case RTL871X_HOSTAPD_GET_WPAIE_STA:
1259
1260                 ret = rtw_get_sta_wpaie(dev, param);
1261
1262                 break;
1263
1264         case RTL871X_HOSTAPD_SET_WPS_BEACON:
1265
1266                 ret = rtw_set_wps_beacon(dev, param, p->length);
1267
1268                 break;
1269
1270         case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
1271
1272                 ret = rtw_set_wps_probe_resp(dev, param, p->length);
1273
1274                 break;
1275
1276         case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
1277
1278                 ret = rtw_set_wps_assoc_resp(dev, param, p->length);
1279
1280                 break;
1281
1282         case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
1283
1284                 ret = rtw_set_hidden_ssid(dev, param, p->length);
1285
1286                 break;
1287
1288         case RTL871X_HOSTAPD_GET_INFO_STA:
1289
1290                 ret = rtw_ioctl_get_sta_data(dev, param, p->length);
1291
1292                 break;
1293
1294         case RTL871X_HOSTAPD_SET_MACADDR_ACL:
1295
1296                 ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
1297
1298                 break;
1299
1300         case RTL871X_HOSTAPD_ACL_ADD_STA:
1301
1302                 ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
1303
1304                 break;
1305
1306         case RTL871X_HOSTAPD_ACL_REMOVE_STA:
1307
1308                 ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
1309
1310                 break;
1311
1312         default:
1313                 ret = -EOPNOTSUPP;
1314                 break;
1315
1316         }
1317
1318         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
1319                 ret = -EFAULT;
1320
1321         kfree(param);
1322         return ret;
1323 }
1324
1325 /*  copy from net/wireless/wext.c end */
1326
1327 int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
1328 {
1329         struct iwreq *wrq = (struct iwreq *)rq;
1330         int ret = 0;
1331
1332         switch (cmd) {
1333         case RTL_IOCTL_WPA_SUPPLICANT:
1334                 ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
1335                 break;
1336         case RTL_IOCTL_HOSTAPD:
1337                 ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
1338                 break;
1339         default:
1340                 ret = -EOPNOTSUPP;
1341                 break;
1342         }
1343
1344         return ret;
1345 }