GNU Linux-libre 5.10.219-gnu1
[releases.git] / drivers / staging / rtl8188eu / 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 #define _IOCTL_LINUX_C_
8
9 #include <linux/ieee80211.h>
10
11 #include <osdep_service.h>
12 #include <drv_types.h>
13 #include <wlan_bssdef.h>
14 #include <rtw_debug.h>
15 #include <wifi.h>
16 #include <rtw_mlme.h>
17 #include <rtw_mlme_ext.h>
18 #include <rtw_ioctl.h>
19 #include <rtw_ioctl_set.h>
20 #include <rtl8188e_hal.h>
21
22 #include <linux/vmalloc.h>
23 #include <linux/etherdevice.h>
24
25 #include "osdep_intf.h"
26
27 #define RTL_IOCTL_WPA_SUPPLICANT        (SIOCIWFIRSTPRIV + 30)
28
29 #define SCAN_ITEM_SIZE 768
30 #define MAX_CUSTOM_LEN 64
31 #define RATE_COUNT 4
32
33 /*  combo scan */
34 #define WEXT_CSCAN_AMOUNT 9
35 #define WEXT_CSCAN_BUF_LEN              360
36 #define WEXT_CSCAN_HEADER               "CSCAN S\x01\x00\x00S\x00"
37 #define WEXT_CSCAN_HEADER_SIZE          12
38 #define WEXT_CSCAN_SSID_SECTION         'S'
39 #define WEXT_CSCAN_CHANNEL_SECTION      'C'
40 #define WEXT_CSCAN_NPROBE_SECTION       'N'
41 #define WEXT_CSCAN_ACTV_DWELL_SECTION   'A'
42 #define WEXT_CSCAN_PASV_DWELL_SECTION   'P'
43 #define WEXT_CSCAN_HOME_DWELL_SECTION   'H'
44 #define WEXT_CSCAN_TYPE_SECTION         'T'
45
46 static u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000,
47         6000000, 9000000, 12000000, 18000000, 24000000, 36000000,
48         48000000, 54000000};
49
50 static const char * const iw_operation_mode[] = {
51         "Auto", "Ad-Hoc", "Managed",  "Master", "Repeater",
52         "Secondary", "Monitor"
53 };
54
55 void indicate_wx_scan_complete_event(struct adapter *padapter)
56 {
57         union iwreq_data wrqu;
58
59         memset(&wrqu, 0, sizeof(union iwreq_data));
60         wireless_send_event(padapter->pnetdev, SIOCGIWSCAN, &wrqu, NULL);
61 }
62
63 void rtw_indicate_wx_assoc_event(struct adapter *padapter)
64 {
65         union iwreq_data wrqu;
66         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
67
68         memset(&wrqu, 0, sizeof(union iwreq_data));
69
70         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
71
72         memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
73
74         DBG_88E_LEVEL(_drv_always_, "assoc success\n");
75         wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
76 }
77
78 void rtw_indicate_wx_disassoc_event(struct adapter *padapter)
79 {
80         union iwreq_data wrqu;
81
82         memset(&wrqu, 0, sizeof(union iwreq_data));
83
84         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
85         eth_zero_addr(wrqu.ap_addr.sa_data);
86
87         DBG_88E_LEVEL(_drv_always_, "indicate disassoc\n");
88         wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
89 }
90
91 static char *translate_scan(struct adapter *padapter,
92                             struct iw_request_info *info,
93                             struct wlan_network *pnetwork,
94                             char *start, char *stop)
95 {
96         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
97         struct iw_event iwe;
98         u16 cap;
99         __le16 le_tmp;
100         u32 ht_ielen = 0;
101         char custom[MAX_CUSTOM_LEN];
102         char *p;
103         u16 max_rate = 0, rate, ht_cap = false;
104         u32 i = 0;
105         u8 bw_40MHz = 0, short_GI = 0;
106         u16 mcs_rate = 0;
107         u8 ss, sq;
108
109         /*  AP MAC address  */
110         iwe.cmd = SIOCGIWAP;
111         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
112
113         memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
114         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
115
116         /* Add the ESSID */
117         iwe.cmd = SIOCGIWESSID;
118         iwe.u.data.flags = 1;
119         iwe.u.data.length = min_t(u16, pnetwork->network.ssid.ssid_length, 32);
120         start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.ssid.ssid);
121
122         /* parsing HT_CAP_IE */
123         p = rtw_get_ie(&pnetwork->network.ies[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.ie_length - 12);
124
125         if (p && ht_ielen > 0) {
126                 struct ieee80211_ht_cap *pht_capie;
127
128                 ht_cap = true;
129
130                 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
131                 memcpy(&mcs_rate, pht_capie->mcs.rx_mask, 2);
132                 bw_40MHz = !!(le16_to_cpu(pht_capie->cap_info) &
133                               IEEE80211_HT_CAP_SUP_WIDTH_20_40);
134                 short_GI = !!(le16_to_cpu(pht_capie->cap_info) &
135                               (IEEE80211_HT_CAP_SGI_20 |
136                                IEEE80211_HT_CAP_SGI_40));
137         }
138
139         /* Add the protocol name */
140         iwe.cmd = SIOCGIWNAME;
141         if ((rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates))) {
142                 if (ht_cap)
143                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
144                 else
145                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
146         } else if ((rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates))) {
147                 if (ht_cap)
148                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
149                 else
150                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
151         } else {
152                 if (ht_cap)
153                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
154                 else
155                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
156         }
157
158         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
159
160           /* Add mode */
161         iwe.cmd = SIOCGIWMODE;
162         memcpy(&le_tmp, rtw_get_capability_from_ie(pnetwork->network.ies), 2);
163
164         cap = le16_to_cpu(le_tmp);
165
166         if (!WLAN_CAPABILITY_IS_STA_BSS(cap)) {
167                 if (cap & WLAN_CAPABILITY_ESS)
168                         iwe.u.mode = IW_MODE_MASTER;
169                 else
170                         iwe.u.mode = IW_MODE_ADHOC;
171
172                 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
173         }
174
175         if (pnetwork->network.Configuration.DSConfig < 1)
176                 pnetwork->network.Configuration.DSConfig = 1;
177
178          /* Add frequency/channel */
179         iwe.cmd = SIOCGIWFREQ;
180         iwe.u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
181         iwe.u.freq.e = 1;
182         iwe.u.freq.i = pnetwork->network.Configuration.DSConfig;
183         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
184
185         /* Add encryption capability */
186         iwe.cmd = SIOCGIWENCODE;
187         if (cap & WLAN_CAPABILITY_PRIVACY)
188                 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
189         else
190                 iwe.u.data.flags = IW_ENCODE_DISABLED;
191         iwe.u.data.length = 0;
192         start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.ssid.ssid);
193
194         /*Add basic and extended rates */
195         max_rate = 0;
196         p = custom;
197         p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
198         while (pnetwork->network.SupportedRates[i] != 0) {
199                 rate = pnetwork->network.SupportedRates[i] & 0x7F;
200                 if (rate > max_rate)
201                         max_rate = rate;
202                 p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom),
203                               "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
204                 i++;
205         }
206
207         if (ht_cap) {
208                 if (mcs_rate & 0x8000)/* MCS15 */
209                         max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : ((short_GI) ? 144 : 130);
210                 else if (mcs_rate & 0x0080)/* MCS7 */
211                         ;
212                 else/* default MCS7 */
213                         max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65);
214
215                 max_rate *= 2; /* Mbps/2; */
216         }
217
218         iwe.cmd = SIOCGIWRATE;
219         iwe.u.bitrate.fixed = 0;
220         iwe.u.bitrate.disabled = 0;
221         iwe.u.bitrate.value = max_rate * 500000;
222         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
223
224         /* parsing WPA/WPA2 IE */
225         {
226                 u8 *buf;
227                 u8 wpa_ie[255], rsn_ie[255];
228                 u16 wpa_len = 0, rsn_len = 0;
229                 u8 *p;
230
231                 buf = kzalloc(MAX_WPA_IE_LEN, GFP_ATOMIC);
232                 if (!buf)
233                         return start;
234
235                 rtw_get_sec_ie(pnetwork->network.ies, pnetwork->network.ie_length, rsn_ie, &rsn_len, wpa_ie, &wpa_len);
236                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid =%s\n", pnetwork->network.ssid.ssid));
237                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len));
238
239                 if (wpa_len > 0) {
240                         p = buf;
241                         p += sprintf(p, "wpa_ie=");
242                         for (i = 0; i < wpa_len; i++)
243                                 p += sprintf(p, "%02x", wpa_ie[i]);
244
245                         memset(&iwe, 0, sizeof(iwe));
246                         iwe.cmd = IWEVCUSTOM;
247                         iwe.u.data.length = strlen(buf);
248                         start = iwe_stream_add_point(info, start, stop, &iwe, buf);
249
250                         memset(&iwe, 0, sizeof(iwe));
251                         iwe.cmd = IWEVGENIE;
252                         iwe.u.data.length = wpa_len;
253                         start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie);
254                 }
255                 if (rsn_len > 0) {
256                         p = buf;
257                         p += sprintf(p, "rsn_ie=");
258                         for (i = 0; i < rsn_len; i++)
259                                 p += sprintf(p, "%02x", rsn_ie[i]);
260                         memset(&iwe, 0, sizeof(iwe));
261                         iwe.cmd = IWEVCUSTOM;
262                         iwe.u.data.length = strlen(buf);
263                         start = iwe_stream_add_point(info, start, stop, &iwe, buf);
264
265                         memset(&iwe, 0, sizeof(iwe));
266                         iwe.cmd = IWEVGENIE;
267                         iwe.u.data.length = rsn_len;
268                         start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie);
269                 }
270                 kfree(buf);
271         }
272
273         {/* parsing WPS IE */
274                 uint cnt = 0, total_ielen;
275                 u8 *wpsie_ptr = NULL;
276                 uint wps_ielen = 0;
277                 u8 *ie_ptr = pnetwork->network.ies + _FIXED_IE_LENGTH_;
278
279                 total_ielen = pnetwork->network.ie_length - _FIXED_IE_LENGTH_;
280
281                 while (cnt < total_ielen) {
282                         if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen > 2)) {
283                                 wpsie_ptr = &ie_ptr[cnt];
284                                 iwe.cmd = IWEVGENIE;
285                                 iwe.u.data.length = (u16)wps_ielen;
286                                 start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr);
287                         }
288                         cnt += ie_ptr[cnt + 1] + 2; /* goto next */
289                 }
290         }
291
292         /* Add quality statistics */
293         iwe.cmd = IWEVQUAL;
294         iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID;
295
296         if (check_fwstate(pmlmepriv, _FW_LINKED) &&
297             is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network)) {
298                 ss = padapter->recvpriv.signal_strength;
299                 sq = padapter->recvpriv.signal_qual;
300         } else {
301                 ss = pnetwork->network.PhyInfo.SignalStrength;
302                 sq = pnetwork->network.PhyInfo.SignalQuality;
303         }
304
305         iwe.u.qual.level = (u8)ss;
306         iwe.u.qual.qual = (u8)sq;   /*  signal quality */
307         iwe.u.qual.noise = 0; /*  noise level */
308         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
309         return start;
310 }
311
312 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
313 {
314         struct adapter *padapter = rtw_netdev_priv(dev);
315         int ret = 0;
316
317         if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
318                 DBG_88E("%s, AUTH_ALG_SHARED_KEY and  AUTH_ALG_OPEN_SYSTEM [value:0x%x]\n", __func__, value);
319                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
320                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
321                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
322         } else if (value & AUTH_ALG_SHARED_KEY) {
323                 DBG_88E("%s, AUTH_ALG_SHARED_KEY  [value:0x%x]\n", __func__, value);
324                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
325
326                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
327                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
328         } else if (value & AUTH_ALG_OPEN_SYSTEM) {
329                 DBG_88E("%s, AUTH_ALG_OPEN_SYSTEM\n", __func__);
330                 if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
331                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
332                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
333                 }
334         } else if (value & AUTH_ALG_LEAP) {
335                 DBG_88E("%s, AUTH_ALG_LEAP\n", __func__);
336         } else {
337                 DBG_88E("%s, error!\n", __func__);
338                 ret = -EINVAL;
339         }
340         return ret;
341 }
342
343 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
344 {
345         int ret = 0;
346         u32 wep_key_idx, wep_key_len, wep_total_len;
347         struct ndis_802_11_wep *pwep = NULL;
348         struct adapter *padapter = rtw_netdev_priv(dev);
349         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
350         struct security_priv *psecuritypriv = &padapter->securitypriv;
351
352         param->u.crypt.err = 0;
353         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
354
355         if (param_len < (u32)((u8 *)param->u.crypt.key - (u8 *)param) + param->u.crypt.key_len) {
356                 ret =  -EINVAL;
357                 goto exit;
358         }
359
360         if (is_broadcast_ether_addr(param->sta_addr)) {
361                 if (param->u.crypt.idx >= WEP_KEYS) {
362                         ret = -EINVAL;
363                         goto exit;
364                 }
365         } else {
366                 ret = -EINVAL;
367                 goto exit;
368         }
369
370         if (strcmp(param->u.crypt.alg, "WEP") == 0) {
371                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("%s, crypt.alg = WEP\n", __func__));
372                 DBG_88E("%s, crypt.alg = WEP\n", __func__);
373
374                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
375                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
376                 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
377
378                 wep_key_idx = param->u.crypt.idx;
379                 wep_key_len = param->u.crypt.key_len;
380
381                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(1)wep_key_idx =%d\n", wep_key_idx));
382                 DBG_88E("(1)wep_key_idx =%d\n", wep_key_idx);
383
384                 if (wep_key_idx > WEP_KEYS)
385                         return -EINVAL;
386
387                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(2)wep_key_idx =%d\n", wep_key_idx));
388
389                 if (wep_key_len > 0) {
390                         wep_key_len = wep_key_len <= 5 ? 5 : 13;
391                         wep_total_len = wep_key_len + offsetof(struct ndis_802_11_wep, KeyMaterial);
392                         pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len);
393                         if (!pwep) {
394                                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("%s: pwep allocate fail !!!\n", __func__));
395                                 goto exit;
396                         }
397                         memset(pwep, 0, wep_total_len);
398                         pwep->KeyLength = wep_key_len;
399                         pwep->Length = wep_total_len;
400                         if (wep_key_len == 13) {
401                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
402                                 padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
403                         }
404                 } else {
405                         ret = -EINVAL;
406                         goto exit;
407                 }
408                 pwep->KeyIndex = wep_key_idx;
409                 pwep->KeyIndex |= 0x80000000;
410                 memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
411                 if (param->u.crypt.set_tx) {
412                         DBG_88E("wep, set_tx = 1\n");
413                         if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
414                                 ret = -EOPNOTSUPP;
415                 } else {
416                         DBG_88E("wep, set_tx = 0\n");
417                         if (wep_key_idx >= WEP_KEYS) {
418                                 ret = -EOPNOTSUPP;
419                                 goto exit;
420                         }
421                         memcpy(&psecuritypriv->dot11DefKey[wep_key_idx].skey[0], pwep->KeyMaterial, pwep->KeyLength);
422                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
423                         rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0);
424                 }
425                 goto exit;
426         }
427
428         if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /*  802_1x */
429                 struct sta_info *psta, *pbcmc_sta;
430                 struct sta_priv *pstapriv = &padapter->stapriv;
431
432                 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { /* sta mode */
433                         psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
434                         if (!psta) {
435                                 ;
436                         } else {
437                                 if (strcmp(param->u.crypt.alg, "none") != 0)
438                                         psta->ieee8021x_blocked = false;
439
440                                 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
441                                     (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))
442                                         psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
443
444                                 if (param->u.crypt.set_tx == 1) { /* pairwise key */
445                                         memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
446
447                                         if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
448                                                 memcpy(psta->dot11tkiptxmickey.skey, &param->u.crypt.key[16], 8);
449                                                 memcpy(psta->dot11tkiprxmickey.skey, &param->u.crypt.key[24], 8);
450                                                 padapter->securitypriv.busetkipkey = false;
451                                         }
452
453                                         DBG_88E(" ~~~~set sta key:unicastkey\n");
454
455                                         rtw_setstakey_cmd(padapter, (unsigned char *)psta, true);
456                                 } else { /* group key */
457                                         memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
458                                         memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[16], 8);
459                                         memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[24], 8);
460                                         padapter->securitypriv.binstallGrpkey = true;
461                                         DBG_88E(" ~~~~set sta key:groupkey\n");
462
463                                         padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
464
465                                         rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1);
466                                 }
467                         }
468                         pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
469                         if (!pbcmc_sta) {
470                                 ;
471                         } else {
472                                 /* Jeff: don't disable ieee8021x_blocked while clearing key */
473                                 if (strcmp(param->u.crypt.alg, "none") != 0)
474                                         pbcmc_sta->ieee8021x_blocked = false;
475
476                                 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
477                                     (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))
478                                         pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
479                         }
480                 }
481         }
482
483 exit:
484
485         kfree(pwep);
486         return ret;
487 }
488
489 static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ielen)
490 {
491         u8 *buf = NULL;
492         int group_cipher = 0, pairwise_cipher = 0;
493         int ret = 0;
494
495         if ((ielen > MAX_WPA_IE_LEN) || (!pie)) {
496                 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
497                 if (!pie)
498                         return ret;
499                 else
500                         return -EINVAL;
501         }
502
503         if (ielen) {
504                 buf = kmemdup(pie, ielen, GFP_KERNEL);
505                 if (!buf) {
506                         ret =  -ENOMEM;
507                         goto exit;
508                 }
509
510                 /* dump */
511                 {
512                         int i;
513
514                         DBG_88E("\n wpa_ie(length:%d):\n", ielen);
515                         for (i = 0; i < ielen; i += 8)
516                                 DBG_88E("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", buf[i], buf[i + 1], buf[i + 2], buf[i + 3], buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7]);
517                 }
518
519                 if (ielen < RSN_HEADER_LEN) {
520                         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("Ie len too short %d\n", ielen));
521                         ret  = -1;
522                         goto exit;
523                 }
524
525                 if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
526                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
527                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
528                         memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
529                 }
530
531                 if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
532                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
533                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
534                         memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
535                 }
536
537                 switch (group_cipher) {
538                 case WPA_CIPHER_NONE:
539                         padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
540                         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
541                         break;
542                 case WPA_CIPHER_WEP40:
543                         padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
544                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
545                         break;
546                 case WPA_CIPHER_TKIP:
547                         padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
548                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
549                         break;
550                 case WPA_CIPHER_CCMP:
551                         padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
552                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
553                         break;
554                 case WPA_CIPHER_WEP104:
555                         padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
556                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
557                         break;
558                 }
559
560                 switch (pairwise_cipher) {
561                 case WPA_CIPHER_NONE:
562                         padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
563                         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
564                         break;
565                 case WPA_CIPHER_WEP40:
566                         padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
567                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
568                         break;
569                 case WPA_CIPHER_TKIP:
570                         padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
571                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
572                         break;
573                 case WPA_CIPHER_CCMP:
574                         padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
575                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
576                         break;
577                 case WPA_CIPHER_WEP104:
578                         padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
579                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
580                         break;
581                 }
582
583                 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
584                 {/* set wps_ie */
585                         u16 cnt = 0;
586                         u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
587
588                         while (cnt < ielen) {
589                                 eid = buf[cnt];
590                                 if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&buf[cnt + 2], wps_oui, 4))) {
591                                         DBG_88E("SET WPS_IE\n");
592
593                                         padapter->securitypriv.wps_ie_len = min(buf[cnt + 1] + 2, MAX_WPA_IE_LEN << 2);
594
595                                         memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
596
597                                         set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
598                                         cnt += buf[cnt + 1] + 2;
599                                         break;
600                                 }
601                                 cnt += buf[cnt + 1] + 2; /* goto next */
602                         }
603                 }
604         }
605
606         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
607                  ("%s: pairwise_cipher = 0x%08x padapter->securitypriv.ndisencryptstatus =%d padapter->securitypriv.ndisauthtype =%d\n",
608                   __func__, pairwise_cipher, padapter->securitypriv.ndisencryptstatus, padapter->securitypriv.ndisauthtype));
609 exit:
610         kfree(buf);
611         return ret;
612 }
613
614 typedef unsigned char   NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX];
615
616 static int rtw_wx_get_name(struct net_device *dev,
617                            struct iw_request_info *info,
618                            union iwreq_data *wrqu, char *extra)
619 {
620         struct adapter *padapter = rtw_netdev_priv(dev);
621         u32 ht_ielen = 0;
622         char *p;
623         u8 ht_cap = false;
624         struct  mlme_priv       *pmlmepriv = &padapter->mlmepriv;
625         struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
626         NDIS_802_11_RATES_EX *prates = NULL;
627
628         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("cmd_code =%x\n", info->cmd));
629
630         if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
631                 /* parsing HT_CAP_IE */
632                 p = rtw_get_ie(&pcur_bss->ies[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->ie_length - 12);
633                 if (p && ht_ielen > 0)
634                         ht_cap = true;
635
636                 prates = &pcur_bss->SupportedRates;
637
638                 if (rtw_is_cckratesonly_included((u8 *)prates)) {
639                         if (ht_cap)
640                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
641                         else
642                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
643                 } else if (rtw_is_cckrates_included((u8 *)prates)) {
644                         if (ht_cap)
645                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
646                         else
647                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
648                 } else {
649                         if (ht_cap)
650                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
651                         else
652                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
653                 }
654         } else {
655                 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
656         }
657         return 0;
658 }
659
660 static int rtw_wx_set_freq(struct net_device *dev,
661                            struct iw_request_info *info,
662                            union iwreq_data *wrqu, char *extra)
663 {
664         RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+%s\n", __func__));
665         return 0;
666 }
667
668 static int rtw_wx_get_freq(struct net_device *dev,
669                            struct iw_request_info *info,
670                            union iwreq_data *wrqu, char *extra)
671 {
672         struct adapter *padapter = rtw_netdev_priv(dev);
673         struct  mlme_priv       *pmlmepriv = &padapter->mlmepriv;
674         struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
675
676         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
677                 /* wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->Configuration.DSConfig-1] * 100000; */
678                 wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000;
679                 wrqu->freq.e = 1;
680                 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
681         } else {
682                 wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
683                 wrqu->freq.e = 1;
684                 wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
685         }
686
687         return 0;
688 }
689
690 static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
691                            union iwreq_data *wrqu, char *b)
692 {
693         struct adapter *padapter = rtw_netdev_priv(dev);
694         enum ndis_802_11_network_infra networkType;
695         int ret = 0;
696
697         if (!rtw_pwr_wakeup(padapter)) {
698                 ret = -EPERM;
699                 goto exit;
700         }
701
702         if (!padapter->hw_init_completed) {
703                 ret = -EPERM;
704                 goto exit;
705         }
706
707         switch (wrqu->mode) {
708         case IW_MODE_AUTO:
709                 networkType = Ndis802_11AutoUnknown;
710                 DBG_88E("set_mode = IW_MODE_AUTO\n");
711                 break;
712         case IW_MODE_ADHOC:
713                 networkType = Ndis802_11IBSS;
714                 DBG_88E("set_mode = IW_MODE_ADHOC\n");
715                 break;
716         case IW_MODE_MASTER:
717                 networkType = Ndis802_11APMode;
718                 DBG_88E("set_mode = IW_MODE_MASTER\n");
719                 break;
720         case IW_MODE_INFRA:
721                 networkType = Ndis802_11Infrastructure;
722                 DBG_88E("set_mode = IW_MODE_INFRA\n");
723                 break;
724         default:
725                 ret = -EINVAL;
726                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("\n Mode: %s is not supported\n", iw_operation_mode[wrqu->mode]));
727                 goto exit;
728         }
729         if (!rtw_set_802_11_infrastructure_mode(padapter, networkType)) {
730                 ret = -EPERM;
731                 goto exit;
732         }
733         rtw_setopmode_cmd(padapter, networkType);
734 exit:
735         return ret;
736 }
737
738 static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
739                            union iwreq_data *wrqu, char *b)
740 {
741         struct adapter *padapter = rtw_netdev_priv(dev);
742         struct  mlme_priv       *pmlmepriv = &padapter->mlmepriv;
743
744         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s\n", __func__));
745
746         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
747                 wrqu->mode = IW_MODE_INFRA;
748         else if  ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
749                   (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
750                 wrqu->mode = IW_MODE_ADHOC;
751         else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
752                 wrqu->mode = IW_MODE_MASTER;
753         else
754                 wrqu->mode = IW_MODE_AUTO;
755
756         return 0;
757 }
758
759 static int rtw_wx_set_pmkid(struct net_device *dev,
760                             struct iw_request_info *a,
761                             union iwreq_data *wrqu, char *extra)
762 {
763         struct adapter *padapter = rtw_netdev_priv(dev);
764         u8   j, blInserted = false;
765         int  ret = false;
766         struct security_priv *psecuritypriv = &padapter->securitypriv;
767         struct iw_pmksa *pPMK = (struct iw_pmksa *)extra;
768         u8     strZeroMacAddress[ETH_ALEN] = {0x00};
769         u8     strIssueBssid[ETH_ALEN] = {0x00};
770
771         memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
772         if (pPMK->cmd == IW_PMKSA_ADD) {
773                 DBG_88E("[%s] IW_PMKSA_ADD!\n", __func__);
774                 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
775                         return ret;
776                 ret = true;
777                 blInserted = false;
778
779                 /* overwrite PMKID */
780                 for (j = 0; j < NUM_PMKID_CACHE; j++) {
781                         if (!memcmp(psecuritypriv->PMKIDList[j].bssid, strIssueBssid, ETH_ALEN)) {
782                                 /*  BSSID is matched, the same AP => rewrite with new PMKID. */
783                                 DBG_88E("[%s] BSSID exists in the PMKList.\n", __func__);
784                                 memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
785                                 psecuritypriv->PMKIDList[j].used = true;
786                                 psecuritypriv->PMKIDIndex = j + 1;
787                                 blInserted = true;
788                                 break;
789                         }
790                 }
791
792                 if (!blInserted) {
793                         /*  Find a new entry */
794                         DBG_88E("[%s] Use the new entry index = %d for this PMKID.\n",
795                                 __func__, psecuritypriv->PMKIDIndex);
796
797                         memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bssid, strIssueBssid, ETH_ALEN);
798                         memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
799
800                         psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].used = true;
801                         psecuritypriv->PMKIDIndex++;
802                         if (psecuritypriv->PMKIDIndex == 16)
803                                 psecuritypriv->PMKIDIndex = 0;
804                 }
805         } else if (pPMK->cmd == IW_PMKSA_REMOVE) {
806                 DBG_88E("[%s] IW_PMKSA_REMOVE!\n", __func__);
807                 ret = true;
808                 for (j = 0; j < NUM_PMKID_CACHE; j++) {
809                         if (!memcmp(psecuritypriv->PMKIDList[j].bssid, strIssueBssid, ETH_ALEN)) {
810                                 /*  BSSID is matched, the same AP => Remove this PMKID information and reset it. */
811                                 eth_zero_addr(psecuritypriv->PMKIDList[j].bssid);
812                                 psecuritypriv->PMKIDList[j].used = false;
813                                 break;
814                         }
815                 }
816         } else if (pPMK->cmd == IW_PMKSA_FLUSH) {
817                 DBG_88E("[%s] IW_PMKSA_FLUSH!\n", __func__);
818                 memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
819                 psecuritypriv->PMKIDIndex = 0;
820                 ret = true;
821         }
822         return ret;
823 }
824
825 static int rtw_wx_get_sens(struct net_device *dev,
826                            struct iw_request_info *info,
827                            union iwreq_data *wrqu, char *extra)
828 {
829         wrqu->sens.value = 0;
830         wrqu->sens.fixed = 0;   /* no auto select */
831         wrqu->sens.disabled = 1;
832         return 0;
833 }
834
835 static int rtw_wx_get_range(struct net_device *dev,
836                             struct iw_request_info *info,
837                             union iwreq_data *wrqu, char *extra)
838 {
839         struct iw_range *range = (struct iw_range *)extra;
840         struct adapter *padapter = rtw_netdev_priv(dev);
841         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
842
843         u16 val;
844         int i;
845
846         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s. cmd_code =%x\n", __func__, info->cmd));
847
848         wrqu->data.length = sizeof(*range);
849         memset(range, 0, sizeof(*range));
850
851         /* Let's try to keep this struct in the same order as in
852          * linux/include/wireless.h
853          */
854
855         /* TODO: See what values we can set, and remove the ones we can't
856          * set, or fill them with some default data.
857          */
858
859         /* ~5 Mb/s real (802.11b) */
860         range->throughput = 5 * 1000 * 1000;
861
862         /* signal level threshold range */
863
864         /* percent values between 0 and 100. */
865         range->max_qual.qual = 100;
866         range->max_qual.level = 100;
867         range->max_qual.noise = 100;
868         range->max_qual.updated = 7; /* Updated all three */
869
870         range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
871         /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
872         range->avg_qual.level = 178; /* -78 dBm */
873         range->avg_qual.noise = 0;
874         range->avg_qual.updated = 7; /* Updated all three */
875
876         range->num_bitrates = RATE_COUNT;
877
878         for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
879                 range->bitrate[i] = rtw_rates[i];
880
881         range->min_frag = MIN_FRAG_THRESHOLD;
882         range->max_frag = MAX_FRAG_THRESHOLD;
883
884         range->pm_capa = 0;
885
886         range->we_version_compiled = WIRELESS_EXT;
887         range->we_version_source = 16;
888
889         for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) {
890                 /*  Include only legal frequencies for some countries */
891                 if (pmlmeext->channel_set[i].ChannelNum != 0) {
892                         range->freq[val].i = pmlmeext->channel_set[i].ChannelNum;
893                         range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000;
894                         range->freq[val].e = 1;
895                         val++;
896                 }
897
898                 if (val == IW_MAX_FREQUENCIES)
899                         break;
900         }
901
902         range->num_channels = val;
903         range->num_frequency = val;
904
905 /*  The following code will proivde the security capability to network manager. */
906 /*  If the driver doesn't provide this capability to network manager, */
907 /*  the WPA/WPA2 routers can't be chosen in the network manager. */
908
909 /*
910 #define IW_SCAN_CAPA_NONE               0x00
911 #define IW_SCAN_CAPA_ESSID              0x01
912 #define IW_SCAN_CAPA_BSSID              0x02
913 #define IW_SCAN_CAPA_CHANNEL            0x04
914 #define IW_SCAN_CAPA_MODE               0x08
915 #define IW_SCAN_CAPA_RATE               0x10
916 #define IW_SCAN_CAPA_TYPE               0x20
917 #define IW_SCAN_CAPA_TIME               0x40
918 */
919
920         range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
921                           IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
922
923         range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE |
924                            IW_SCAN_CAPA_BSSID | IW_SCAN_CAPA_CHANNEL |
925                            IW_SCAN_CAPA_MODE | IW_SCAN_CAPA_RATE;
926         return 0;
927 }
928
929 /* set bssid flow */
930 /* s1. rtw_set_802_11_infrastructure_mode() */
931 /* s2. rtw_set_802_11_authentication_mode() */
932 /* s3. set_802_11_encryption_mode() */
933 /* s4. rtw_set_802_11_bssid() */
934 static int rtw_wx_set_wap(struct net_device *dev,
935                           struct iw_request_info *info,
936                           union iwreq_data *awrq, char *extra)
937 {
938         uint ret = 0;
939         struct adapter *padapter = rtw_netdev_priv(dev);
940         struct sockaddr *temp = (struct sockaddr *)awrq;
941         struct  mlme_priv       *pmlmepriv = &padapter->mlmepriv;
942         struct list_head *phead;
943         u8 *dst_bssid, *src_bssid;
944         struct __queue *queue   = &pmlmepriv->scanned_queue;
945         struct  wlan_network    *pnetwork = NULL;
946         enum ndis_802_11_auth_mode      authmode;
947
948         if (!rtw_pwr_wakeup(padapter)) {
949                 ret = -1;
950                 goto exit;
951         }
952
953         if (!padapter->bup) {
954                 ret = -1;
955                 goto exit;
956         }
957
958         if (temp->sa_family != ARPHRD_ETHER) {
959                 ret = -EINVAL;
960                 goto exit;
961         }
962
963         authmode = padapter->securitypriv.ndisauthtype;
964         spin_lock_bh(&queue->lock);
965         phead = get_list_head(queue);
966         pmlmepriv->pscanned = phead->next;
967
968         while (phead != pmlmepriv->pscanned) {
969                 pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
970
971                 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
972
973                 dst_bssid = pnetwork->network.MacAddress;
974
975                 src_bssid = temp->sa_data;
976
977                 if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) {
978                         if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
979                                 ret = -1;
980                                 spin_unlock_bh(&queue->lock);
981                                 goto exit;
982                         }
983
984                                 break;
985                 }
986         }
987         spin_unlock_bh(&queue->lock);
988
989         rtw_set_802_11_authentication_mode(padapter, authmode);
990         if (!rtw_set_802_11_bssid(padapter, temp->sa_data)) {
991                 ret = -1;
992                 goto exit;
993         }
994
995 exit:
996
997         return ret;
998 }
999
1000 static int rtw_wx_get_wap(struct net_device *dev,
1001                           struct iw_request_info *info,
1002                           union iwreq_data *wrqu, char *extra)
1003 {
1004         struct adapter *padapter = rtw_netdev_priv(dev);
1005         struct  mlme_priv       *pmlmepriv = &padapter->mlmepriv;
1006         struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
1007
1008         wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1009
1010         eth_zero_addr(wrqu->ap_addr.sa_data);
1011
1012         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s\n", __func__));
1013
1014         if (check_fwstate(pmlmepriv, _FW_LINKED) ||
1015             check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1016             check_fwstate(pmlmepriv, WIFI_AP_STATE))
1017                 memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1018         else
1019                 eth_zero_addr(wrqu->ap_addr.sa_data);
1020         return 0;
1021 }
1022
1023 static int rtw_wx_set_mlme(struct net_device *dev,
1024                            struct iw_request_info *info,
1025                            union iwreq_data *wrqu, char *extra)
1026 {
1027         int ret = 0;
1028         u16 reason;
1029         struct adapter *padapter = rtw_netdev_priv(dev);
1030         struct iw_mlme *mlme = (struct iw_mlme *)extra;
1031
1032         if (!mlme)
1033                 return -1;
1034
1035         DBG_88E("%s\n", __func__);
1036
1037         reason = mlme->reason_code;
1038
1039         DBG_88E("%s, cmd =%d, reason =%d\n", __func__, mlme->cmd, reason);
1040
1041         switch (mlme->cmd) {
1042         case IW_MLME_DEAUTH:
1043                 if (!rtw_set_802_11_disassociate(padapter))
1044                         ret = -1;
1045                 break;
1046         case IW_MLME_DISASSOC:
1047                 if (!rtw_set_802_11_disassociate(padapter))
1048                         ret = -1;
1049                 break;
1050         default:
1051                 return -EOPNOTSUPP;
1052         }
1053         return ret;
1054 }
1055
1056 static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
1057                            union iwreq_data *wrqu, char *extra)
1058 {
1059         u8 _status = false;
1060         int ret = 0;
1061         struct adapter *padapter = rtw_netdev_priv(dev);
1062         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1063         struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
1064
1065         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s\n", __func__));
1066
1067         if (!rtw_pwr_wakeup(padapter)) {
1068                 ret = -1;
1069                 goto exit;
1070         }
1071
1072         if (padapter->bDriverStopped) {
1073                 DBG_88E("bDriverStopped =%d\n", padapter->bDriverStopped);
1074                 ret = -1;
1075                 goto exit;
1076         }
1077
1078         if (!padapter->bup) {
1079                 ret = -1;
1080                 goto exit;
1081         }
1082
1083         if (!padapter->hw_init_completed) {
1084                 ret = -1;
1085                 goto exit;
1086         }
1087
1088         /*  When Busy Traffic, driver do not site survey. So driver return success. */
1089         /*  wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */
1090         /*  modify by thomas 2011-02-22. */
1091         if (pmlmepriv->LinkDetectInfo.bBusyTraffic) {
1092                 indicate_wx_scan_complete_event(padapter);
1093                 goto exit;
1094         }
1095
1096         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) {
1097                 indicate_wx_scan_complete_event(padapter);
1098                 goto exit;
1099         }
1100
1101 /*      For the DMP WiFi Display project, the driver won't to scan because */
1102 /*      the pmlmepriv->scan_interval is always equal to 3. */
1103 /*      So, the wpa_supplicant won't find out the WPS SoftAP. */
1104
1105         memset(ssid, 0, sizeof(struct ndis_802_11_ssid) * RTW_SSID_SCAN_AMOUNT);
1106
1107         if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1108                 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1109
1110                 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1111                         int len = min_t(int, req->essid_len,
1112                                         IW_ESSID_MAX_SIZE);
1113
1114                         memcpy(ssid[0].ssid, req->essid, len);
1115                         ssid[0].ssid_length = len;
1116
1117                         DBG_88E("IW_SCAN_THIS_ESSID, ssid =%s, len =%d\n", req->essid, req->essid_len);
1118
1119                         spin_lock_bh(&pmlmepriv->lock);
1120
1121                         _status = rtw_sitesurvey_cmd(padapter, ssid, 1, NULL, 0);
1122
1123                         spin_unlock_bh(&pmlmepriv->lock);
1124                 } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) {
1125                         DBG_88E("%s, req->scan_type == IW_SCAN_TYPE_PASSIVE\n", __func__);
1126                 }
1127         } else {
1128                 if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE &&
1129                     !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
1130                         int len = wrqu->data.length - WEXT_CSCAN_HEADER_SIZE;
1131                         char *pos = extra + WEXT_CSCAN_HEADER_SIZE;
1132                         char section;
1133                         char sec_len;
1134                         int ssid_index = 0;
1135
1136                         while (len >= 1) {
1137                                 section = *(pos++);
1138                                 len -= 1;
1139
1140                                 switch (section) {
1141                                 case WEXT_CSCAN_SSID_SECTION:
1142                                         if (len < 1) {
1143                                                 len = 0;
1144                                                 break;
1145                                         }
1146                                         sec_len = *(pos++); len -= 1;
1147                                         if (sec_len > 0 &&
1148                                             sec_len <= len &&
1149                                             sec_len <= 32) {
1150                                                 ssid[ssid_index].ssid_length = sec_len;
1151                                                 memcpy(ssid[ssid_index].ssid, pos, sec_len);
1152                                                 ssid_index++;
1153                                         }
1154                                         pos += sec_len;
1155                                         len -= sec_len;
1156                                         break;
1157                                 case WEXT_CSCAN_TYPE_SECTION:
1158                                 case WEXT_CSCAN_CHANNEL_SECTION:
1159                                         pos += 1;
1160                                         len -= 1;
1161                                         break;
1162                                 case WEXT_CSCAN_PASV_DWELL_SECTION:
1163                                 case WEXT_CSCAN_HOME_DWELL_SECTION:
1164                                 case WEXT_CSCAN_ACTV_DWELL_SECTION:
1165                                         pos += 2;
1166                                         len -= 2;
1167                                         break;
1168                                 default:
1169                                         len = 0; /*  stop parsing */
1170                                 }
1171                         }
1172
1173                         /* it has still some scan parameter to parse, we only do this now... */
1174                         _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
1175                 } else {
1176                         _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
1177                 }
1178         }
1179
1180         if (!_status)
1181                 ret = -1;
1182
1183 exit:
1184
1185         return ret;
1186 }
1187
1188 static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
1189                            union iwreq_data *wrqu, char *extra)
1190 {
1191         struct list_head *plist, *phead;
1192         struct adapter *padapter = rtw_netdev_priv(dev);
1193         struct  mlme_priv       *pmlmepriv = &padapter->mlmepriv;
1194         struct __queue *queue   = &pmlmepriv->scanned_queue;
1195         struct  wlan_network    *pnetwork = NULL;
1196         char *ev = extra;
1197         char *stop = ev + wrqu->data.length;
1198         u32 ret = 0;
1199         u32 cnt = 0;
1200         u32 wait_for_surveydone;
1201         int wait_status;
1202
1203         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s\n", __func__));
1204         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, (" Start of Query SIOCGIWSCAN .\n"));
1205
1206         if (padapter->pwrctrlpriv.brfoffbyhw && padapter->bDriverStopped) {
1207                 ret = -EINVAL;
1208                 goto exit;
1209         }
1210
1211         wait_for_surveydone = 100;
1212
1213         wait_status = _FW_UNDER_SURVEY | _FW_UNDER_LINKING;
1214
1215         while (check_fwstate(pmlmepriv, wait_status)) {
1216                 msleep(30);
1217                 cnt++;
1218                 if (cnt > wait_for_surveydone)
1219                         break;
1220         }
1221
1222         spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1223
1224         phead = get_list_head(queue);
1225         plist = phead->next;
1226
1227         while (phead != plist) {
1228                 if ((stop - ev) < SCAN_ITEM_SIZE) {
1229                         ret = -E2BIG;
1230                         break;
1231                 }
1232
1233                 pnetwork = container_of(plist, struct wlan_network, list);
1234
1235                 /* report network only if the current channel set contains the channel to which this network belongs */
1236                 if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0)
1237                         ev = translate_scan(padapter, a, pnetwork, ev, stop);
1238
1239                 plist = plist->next;
1240         }
1241
1242         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1243
1244         wrqu->data.length = ev - extra;
1245         wrqu->data.flags = 0;
1246
1247 exit:
1248         return ret;
1249 }
1250
1251 /* set ssid flow */
1252 /* s1. rtw_set_802_11_infrastructure_mode() */
1253 /* s2. set_802_11_authenticaion_mode() */
1254 /* s3. set_802_11_encryption_mode() */
1255 /* s4. rtw_set_802_11_ssid() */
1256 static int rtw_wx_set_essid(struct net_device *dev,
1257                             struct iw_request_info *a,
1258                             union iwreq_data *wrqu, char *extra)
1259 {
1260         struct adapter *padapter = rtw_netdev_priv(dev);
1261         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1262         struct __queue *queue = &pmlmepriv->scanned_queue;
1263         struct list_head *phead;
1264         struct wlan_network *pnetwork = NULL;
1265         enum ndis_802_11_auth_mode authmode;
1266         struct ndis_802_11_ssid ndis_ssid;
1267         u8 *dst_ssid, *src_ssid;
1268
1269         uint ret = 0, len;
1270
1271         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1272                  ("+%s: fw_state = 0x%08x\n", __func__, get_fwstate(pmlmepriv)));
1273         if (!rtw_pwr_wakeup(padapter)) {
1274                 ret = -1;
1275                 goto exit;
1276         }
1277
1278         if (!padapter->bup) {
1279                 ret = -1;
1280                 goto exit;
1281         }
1282
1283         if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
1284                 ret = -E2BIG;
1285                 goto exit;
1286         }
1287
1288         if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1289                 ret = -1;
1290                 goto exit;
1291         }
1292
1293         authmode = padapter->securitypriv.ndisauthtype;
1294         DBG_88E("=>%s\n", __func__);
1295         if (wrqu->essid.flags && wrqu->essid.length) {
1296                 len = min_t(uint, wrqu->essid.length, IW_ESSID_MAX_SIZE);
1297
1298                 if (wrqu->essid.length != 33)
1299                         DBG_88E("ssid =%s, len =%d\n", extra, wrqu->essid.length);
1300
1301                 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1302                 ndis_ssid.ssid_length = len;
1303                 memcpy(ndis_ssid.ssid, extra, len);
1304                 src_ssid = ndis_ssid.ssid;
1305
1306                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("%s: ssid =[%s]\n", __func__, src_ssid));
1307                 spin_lock_bh(&queue->lock);
1308                 phead = get_list_head(queue);
1309                 pmlmepriv->pscanned = phead->next;
1310
1311                 while (phead != pmlmepriv->pscanned) {
1312                         pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
1313
1314                         pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1315
1316                         dst_ssid = pnetwork->network.ssid.ssid;
1317
1318                         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1319                                  ("%s: dst_ssid =%s\n", __func__,
1320                                   pnetwork->network.ssid.ssid));
1321
1322                         if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.ssid_length)) &&
1323                             (pnetwork->network.ssid.ssid_length == ndis_ssid.ssid_length)) {
1324                                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1325                                          ("%s: find match, set infra mode\n", __func__));
1326
1327                                 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1328                                         if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
1329                                                 continue;
1330                                 }
1331
1332                                 if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
1333                                         ret = -1;
1334                                         spin_unlock_bh(&queue->lock);
1335                                         goto exit;
1336                                 }
1337
1338                                 break;
1339                         }
1340                 }
1341                 spin_unlock_bh(&queue->lock);
1342                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1343                          ("set ssid: set_802_11_auth. mode =%d\n", authmode));
1344                 rtw_set_802_11_authentication_mode(padapter, authmode);
1345                 if (!rtw_set_802_11_ssid(padapter, &ndis_ssid)) {
1346                         ret = -1;
1347                         goto exit;
1348                 }
1349         }
1350
1351 exit:
1352         DBG_88E("<=%s, ret %d\n", __func__, ret);
1353
1354         return ret;
1355 }
1356
1357 static int rtw_wx_get_essid(struct net_device *dev,
1358                             struct iw_request_info *a,
1359                             union iwreq_data *wrqu, char *extra)
1360 {
1361         u32 len;
1362         struct adapter *padapter = rtw_netdev_priv(dev);
1363         struct  mlme_priv       *pmlmepriv = &padapter->mlmepriv;
1364         struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
1365
1366         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s\n", __func__));
1367
1368         if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
1369             (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) {
1370                 len = pcur_bss->ssid.ssid_length;
1371                 memcpy(extra, pcur_bss->ssid.ssid, len);
1372         } else {
1373                 len = 0;
1374                 *extra = 0;
1375         }
1376         wrqu->essid.length = len;
1377         wrqu->essid.flags = 1;
1378
1379         return 0;
1380 }
1381
1382 static int rtw_wx_set_rate(struct net_device *dev,
1383                            struct iw_request_info *a,
1384                            union iwreq_data *wrqu, char *extra)
1385 {
1386         int i;
1387         u8 datarates[NumRates];
1388         u32     target_rate = wrqu->bitrate.value;
1389         u32     fixed = wrqu->bitrate.fixed;
1390         u32     ratevalue = 0;
1391         u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1392
1393         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s\n", __func__));
1394         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("target_rate = %d, fixed = %d\n", target_rate, fixed));
1395
1396         if (target_rate == -1) {
1397                 ratevalue = 11;
1398                 goto set_rate;
1399         }
1400         target_rate /= 100000;
1401
1402         switch (target_rate) {
1403         case 10:
1404                 ratevalue = 0;
1405                 break;
1406         case 20:
1407                 ratevalue = 1;
1408                 break;
1409         case 55:
1410                 ratevalue = 2;
1411                 break;
1412         case 60:
1413                 ratevalue = 3;
1414                 break;
1415         case 90:
1416                 ratevalue = 4;
1417                 break;
1418         case 110:
1419                 ratevalue = 5;
1420                 break;
1421         case 120:
1422                 ratevalue = 6;
1423                 break;
1424         case 180:
1425                 ratevalue = 7;
1426                 break;
1427         case 240:
1428                 ratevalue = 8;
1429                 break;
1430         case 360:
1431                 ratevalue = 9;
1432                 break;
1433         case 480:
1434                 ratevalue = 10;
1435                 break;
1436         case 540:
1437                 ratevalue = 11;
1438                 break;
1439         default:
1440                 ratevalue = 11;
1441                 break;
1442         }
1443
1444 set_rate:
1445
1446         for (i = 0; i < NumRates; i++) {
1447                 if (ratevalue == mpdatarate[i]) {
1448                         datarates[i] = mpdatarate[i];
1449                         if (fixed == 0)
1450                                 break;
1451                 } else {
1452                         datarates[i] = 0xff;
1453                 }
1454
1455                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("datarate_inx =%d\n", datarates[i]));
1456         }
1457
1458         return 0;
1459 }
1460
1461 static int rtw_wx_get_rate(struct net_device *dev,
1462                            struct iw_request_info *info,
1463                            union iwreq_data *wrqu, char *extra)
1464 {
1465         u16 max_rate = 0;
1466
1467         max_rate = rtw_get_cur_max_rate(rtw_netdev_priv(dev));
1468
1469         if (max_rate == 0)
1470                 return -EPERM;
1471
1472         wrqu->bitrate.fixed = 0;        /* no auto select */
1473         wrqu->bitrate.value = max_rate * 100000;
1474
1475         return 0;
1476 }
1477
1478 static int rtw_wx_set_rts(struct net_device *dev,
1479                           struct iw_request_info *info,
1480                           union iwreq_data *wrqu, char *extra)
1481 {
1482         struct adapter *padapter = rtw_netdev_priv(dev);
1483
1484         if (wrqu->rts.disabled) {
1485                 padapter->registrypriv.rts_thresh = 2347;
1486         } else {
1487                 if (wrqu->rts.value < 0 ||
1488                     wrqu->rts.value > 2347)
1489                         return -EINVAL;
1490
1491                 padapter->registrypriv.rts_thresh = wrqu->rts.value;
1492         }
1493
1494         DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
1495
1496         return 0;
1497 }
1498
1499 static int rtw_wx_get_rts(struct net_device *dev,
1500                           struct iw_request_info *info,
1501                           union iwreq_data *wrqu, char *extra)
1502 {
1503         struct adapter *padapter = rtw_netdev_priv(dev);
1504
1505         DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
1506
1507         wrqu->rts.value = padapter->registrypriv.rts_thresh;
1508         wrqu->rts.fixed = 0;    /* no auto select */
1509         /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */
1510
1511         return 0;
1512 }
1513
1514 static int rtw_wx_set_frag(struct net_device *dev,
1515                            struct iw_request_info *info,
1516                            union iwreq_data *wrqu, char *extra)
1517 {
1518         struct adapter *padapter = rtw_netdev_priv(dev);
1519
1520         if (wrqu->frag.disabled) {
1521                 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1522         } else {
1523                 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1524                     wrqu->frag.value > MAX_FRAG_THRESHOLD)
1525                         return -EINVAL;
1526
1527                 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1528         }
1529
1530         DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
1531
1532         return 0;
1533 }
1534
1535 static int rtw_wx_get_frag(struct net_device *dev,
1536                            struct iw_request_info *info,
1537                            union iwreq_data *wrqu, char *extra)
1538 {
1539         struct adapter *padapter = rtw_netdev_priv(dev);
1540
1541         DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
1542
1543         wrqu->frag.value = padapter->xmitpriv.frag_len;
1544         wrqu->frag.fixed = 0;   /* no auto select */
1545
1546         return 0;
1547 }
1548
1549 static int rtw_wx_get_retry(struct net_device *dev,
1550                             struct iw_request_info *info,
1551                             union iwreq_data *wrqu, char *extra)
1552 {
1553         wrqu->retry.value = 7;
1554         wrqu->retry.fixed = 0;  /* no auto select */
1555         wrqu->retry.disabled = 1;
1556
1557         return 0;
1558 }
1559
1560 static int rtw_wx_set_enc(struct net_device *dev,
1561                           struct iw_request_info *info,
1562                           union iwreq_data *wrqu, char *keybuf)
1563 {
1564         u32 key, ret = 0;
1565         u32 keyindex_provided;
1566         struct ndis_802_11_wep   wep;
1567         enum ndis_802_11_auth_mode authmode;
1568
1569         struct iw_point *erq = &wrqu->encoding;
1570         struct adapter *padapter = rtw_netdev_priv(dev);
1571         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
1572
1573         DBG_88E("+%s, flags = 0x%x\n", __func__, erq->flags);
1574
1575         memset(&wep, 0, sizeof(struct ndis_802_11_wep));
1576
1577         key = erq->flags & IW_ENCODE_INDEX;
1578
1579         if (erq->flags & IW_ENCODE_DISABLED) {
1580                 DBG_88E("EncryptionDisabled\n");
1581                 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1582                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1583                 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1584                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1585                 authmode = Ndis802_11AuthModeOpen;
1586                 padapter->securitypriv.ndisauthtype = authmode;
1587
1588                 goto exit;
1589         }
1590
1591         if (key) {
1592                 if (key > WEP_KEYS)
1593                         return -EINVAL;
1594                 key--;
1595                 keyindex_provided = 1;
1596         } else {
1597                 keyindex_provided = 0;
1598                 key = padapter->securitypriv.dot11PrivacyKeyIndex;
1599                 DBG_88E("%s, key =%d\n", __func__, key);
1600         }
1601
1602         /* set authentication mode */
1603         if (erq->flags & IW_ENCODE_OPEN) {
1604                 DBG_88E("%s():IW_ENCODE_OPEN\n", __func__);
1605                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1606                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1607                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1608                 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1609                 authmode = Ndis802_11AuthModeOpen;
1610                 padapter->securitypriv.ndisauthtype = authmode;
1611         } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1612                 DBG_88E("%s():IW_ENCODE_RESTRICTED\n", __func__);
1613                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1614                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1615                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1616                 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
1617                 authmode = Ndis802_11AuthModeShared;
1618                 padapter->securitypriv.ndisauthtype = authmode;
1619         } else {
1620                 DBG_88E("%s():erq->flags = 0x%x\n", __func__, erq->flags);
1621
1622                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1623                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1624                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1625                 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1626                 authmode = Ndis802_11AuthModeOpen;
1627                 padapter->securitypriv.ndisauthtype = authmode;
1628         }
1629
1630         wep.KeyIndex = key;
1631         if (erq->length > 0) {
1632                 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1633
1634                 wep.Length = wep.KeyLength + offsetof(struct ndis_802_11_wep, KeyMaterial);
1635         } else {
1636                 wep.KeyLength = 0;
1637
1638                 if (keyindex_provided == 1) {
1639                         /*  set key_id only, no given KeyMaterial(erq->length == 0). */
1640                         padapter->securitypriv.dot11PrivacyKeyIndex = key;
1641
1642                         DBG_88E("(keyindex_provided == 1), keyid =%d, key_len =%d\n", key, padapter->securitypriv.dot11DefKeylen[key]);
1643
1644                         switch (padapter->securitypriv.dot11DefKeylen[key]) {
1645                         case 5:
1646                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1647                                 break;
1648                         case 13:
1649                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
1650                                 break;
1651                         default:
1652                                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1653                                 break;
1654                         }
1655
1656                         goto exit;
1657                 }
1658         }
1659
1660         wep.KeyIndex |= 0x80000000;
1661
1662         memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1663
1664         if (!rtw_set_802_11_add_wep(padapter, &wep)) {
1665                 if (rf_on == pwrpriv->rf_pwrstate)
1666                         ret = -EOPNOTSUPP;
1667                 goto exit;
1668         }
1669
1670 exit:
1671         return ret;
1672 }
1673
1674 static int rtw_wx_get_enc(struct net_device *dev,
1675                           struct iw_request_info *info,
1676                           union iwreq_data *wrqu, char *keybuf)
1677 {
1678         uint key;
1679         struct adapter *padapter = rtw_netdev_priv(dev);
1680         struct iw_point *erq = &wrqu->encoding;
1681         struct  mlme_priv       *pmlmepriv = &padapter->mlmepriv;
1682
1683         if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
1684                 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1685                         erq->length = 0;
1686                         erq->flags |= IW_ENCODE_DISABLED;
1687                         return 0;
1688                 }
1689         }
1690
1691         key = erq->flags & IW_ENCODE_INDEX;
1692
1693         if (key) {
1694                 if (key > WEP_KEYS)
1695                         return -EINVAL;
1696                 key--;
1697         } else {
1698                 key = padapter->securitypriv.dot11PrivacyKeyIndex;
1699         }
1700
1701         erq->flags = key + 1;
1702
1703         switch (padapter->securitypriv.ndisencryptstatus) {
1704         case Ndis802_11EncryptionNotSupported:
1705         case Ndis802_11EncryptionDisabled:
1706                 erq->length = 0;
1707                 erq->flags |= IW_ENCODE_DISABLED;
1708                 break;
1709         case Ndis802_11Encryption1Enabled:
1710                 erq->length = padapter->securitypriv.dot11DefKeylen[key];
1711                 if (erq->length) {
1712                         memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
1713
1714                         erq->flags |= IW_ENCODE_ENABLED;
1715
1716                         if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
1717                                 erq->flags |= IW_ENCODE_OPEN;
1718                         else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
1719                                 erq->flags |= IW_ENCODE_RESTRICTED;
1720                 } else {
1721                         erq->length = 0;
1722                         erq->flags |= IW_ENCODE_DISABLED;
1723                 }
1724                 break;
1725         case Ndis802_11Encryption2Enabled:
1726         case Ndis802_11Encryption3Enabled:
1727                 erq->length = 16;
1728                 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
1729                 break;
1730         default:
1731                 erq->length = 0;
1732                 erq->flags |= IW_ENCODE_DISABLED;
1733                 break;
1734         }
1735
1736         return 0;
1737 }
1738
1739 static int rtw_wx_get_power(struct net_device *dev,
1740                             struct iw_request_info *info,
1741                             union iwreq_data *wrqu, char *extra)
1742 {
1743         wrqu->power.value = 0;
1744         wrqu->power.fixed = 0;  /* no auto select */
1745         wrqu->power.disabled = 1;
1746
1747         return 0;
1748 }
1749
1750 static int rtw_wx_set_gen_ie(struct net_device *dev,
1751                              struct iw_request_info *info,
1752                              union iwreq_data *wrqu, char *extra)
1753 {
1754         struct adapter *padapter = rtw_netdev_priv(dev);
1755
1756         return rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
1757 }
1758
1759 static int rtw_wx_set_auth(struct net_device *dev,
1760                            struct iw_request_info *info,
1761                            union iwreq_data *wrqu, char *extra)
1762 {
1763         struct adapter *padapter = rtw_netdev_priv(dev);
1764         struct iw_param *param = (struct iw_param *)&wrqu->param;
1765         int ret = 0;
1766
1767         switch (param->flags & IW_AUTH_INDEX) {
1768         case IW_AUTH_WPA_VERSION:
1769                 break;
1770         case IW_AUTH_CIPHER_PAIRWISE:
1771
1772                 break;
1773         case IW_AUTH_CIPHER_GROUP:
1774
1775                 break;
1776         case IW_AUTH_KEY_MGMT:
1777                 /*
1778                  *  ??? does not use these parameters
1779                  */
1780                 break;
1781         case IW_AUTH_TKIP_COUNTERMEASURES:
1782                 if (param->value) {
1783                         /*  wpa_supplicant is enabling the tkip countermeasure. */
1784                         padapter->securitypriv.btkip_countermeasure = true;
1785                 } else {
1786                         /*  wpa_supplicant is disabling the tkip countermeasure. */
1787                         padapter->securitypriv.btkip_countermeasure = false;
1788                 }
1789                 break;
1790         case IW_AUTH_DROP_UNENCRYPTED:
1791                 /* HACK:
1792                  *
1793                  * wpa_supplicant calls set_wpa_enabled when the driver
1794                  * is loaded and unloaded, regardless of if WPA is being
1795                  * used.  No other calls are made which can be used to
1796                  * determine if encryption will be used or not prior to
1797                  * association being expected.  If encryption is not being
1798                  * used, drop_unencrypted is set to false, else true -- we
1799                  * can use this to determine if the CAP_PRIVACY_ON bit should
1800                  * be set.
1801                  */
1802
1803                 if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled)
1804                         break;/* it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled, */
1805                                         /*  then it needn't reset it; */
1806
1807                 if (param->value) {
1808                         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1809                         padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1810                         padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1811                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1812                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
1813                 }
1814
1815                 break;
1816         case IW_AUTH_80211_AUTH_ALG:
1817                 /* It's the starting point of a link layer connection using wpa_supplicant */
1818                 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
1819                         LeaveAllPowerSaveMode(padapter);
1820                         rtw_disassoc_cmd(padapter, 500, false);
1821                         DBG_88E("%s...call rtw_indicate_disconnect\n ", __func__);
1822                         rtw_indicate_disconnect(padapter);
1823                         rtw_free_assoc_resources(padapter);
1824                 }
1825                 ret = wpa_set_auth_algs(dev, (u32)param->value);
1826                 break;
1827         case IW_AUTH_WPA_ENABLED:
1828                 break;
1829         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1830                 break;
1831         case IW_AUTH_PRIVACY_INVOKED:
1832                 break;
1833         default:
1834                 return -EOPNOTSUPP;
1835         }
1836
1837         return ret;
1838 }
1839
1840 static int rtw_wx_set_enc_ext(struct net_device *dev,
1841                               struct iw_request_info *info,
1842                               union iwreq_data *wrqu, char *extra)
1843 {
1844         char *alg_name;
1845         u32 param_len;
1846         struct ieee_param *param = NULL;
1847         struct iw_point *pencoding = &wrqu->encoding;
1848         struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1849         int ret = 0;
1850
1851         param_len = sizeof(struct ieee_param) + pext->key_len;
1852         param = (struct ieee_param *)rtw_malloc(param_len);
1853         if (!param)
1854                 return -1;
1855
1856         memset(param, 0, param_len);
1857
1858         param->cmd = IEEE_CMD_SET_ENCRYPTION;
1859         eth_broadcast_addr(param->sta_addr);
1860
1861         switch (pext->alg) {
1862         case IW_ENCODE_ALG_NONE:
1863                 /* todo: remove key */
1864                 /* remove = 1; */
1865                 alg_name = "none";
1866                 break;
1867         case IW_ENCODE_ALG_WEP:
1868                 alg_name = "WEP";
1869                 break;
1870         case IW_ENCODE_ALG_TKIP:
1871                 alg_name = "TKIP";
1872                 break;
1873         case IW_ENCODE_ALG_CCMP:
1874                 alg_name = "CCMP";
1875                 break;
1876         default:
1877                 ret = -1;
1878                 goto exit;
1879         }
1880
1881         strlcpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1882
1883         if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1884                 param->u.crypt.set_tx = 1;
1885
1886         /* cliW: WEP does not have group key
1887          * just not checking GROUP key setting
1888          */
1889         if ((pext->alg != IW_ENCODE_ALG_WEP) &&
1890             (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY))
1891                 param->u.crypt.set_tx = 0;
1892
1893         param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
1894
1895         if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1896                 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1897
1898         if (pext->key_len) {
1899                 param->u.crypt.key_len = pext->key_len;
1900                 memcpy(param->u.crypt.key, pext + 1, pext->key_len);
1901         }
1902
1903         ret =  wpa_set_encryption(dev, param, param_len);
1904
1905 exit:
1906         kfree(param);
1907         return ret;
1908 }
1909
1910 static int rtw_wx_get_nick(struct net_device *dev,
1911                            struct iw_request_info *info,
1912                            union iwreq_data *wrqu, char *extra)
1913 {
1914         if (extra) {
1915                 wrqu->data.length = 14;
1916                 wrqu->data.flags = 1;
1917                 memcpy(extra, "<WIFI@REALTEK>", 14);
1918         }
1919
1920         /* dump debug info here */
1921         return 0;
1922 }
1923
1924 static int dummy(struct net_device *dev, struct iw_request_info *a,
1925                  union iwreq_data *wrqu, char *b)
1926 {
1927         return -1;
1928 }
1929
1930 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
1931 {
1932         uint ret = 0;
1933         struct adapter *padapter = rtw_netdev_priv(dev);
1934
1935         switch (name) {
1936         case IEEE_PARAM_WPA_ENABLED:
1937                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */
1938                 switch (value & 0xff) {
1939                 case 1: /* WPA */
1940                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
1941                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
1942                         break;
1943                 case 2: /* WPA2 */
1944                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
1945                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
1946                         break;
1947                 }
1948                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1949                          ("%s:padapter->securitypriv.ndisauthtype =%d\n", __func__, padapter->securitypriv.ndisauthtype));
1950                 break;
1951         case IEEE_PARAM_TKIP_COUNTERMEASURES:
1952                 break;
1953         case IEEE_PARAM_DROP_UNENCRYPTED: {
1954                 /* HACK:
1955                  *
1956                  * wpa_supplicant calls set_wpa_enabled when the driver
1957                  * is loaded and unloaded, regardless of if WPA is being
1958                  * used.  No other calls are made which can be used to
1959                  * determine if encryption will be used or not prior to
1960                  * association being expected.  If encryption is not being
1961                  * used, drop_unencrypted is set to false, else true -- we
1962                  * can use this to determine if the CAP_PRIVACY_ON bit should
1963                  * be set.
1964                  */
1965
1966                 break;
1967         }
1968         case IEEE_PARAM_PRIVACY_INVOKED:
1969                 break;
1970
1971         case IEEE_PARAM_AUTH_ALGS:
1972                 ret = wpa_set_auth_algs(dev, value);
1973                 break;
1974         case IEEE_PARAM_IEEE_802_1X:
1975                 break;
1976         case IEEE_PARAM_WPAX_SELECT:
1977                 break;
1978         default:
1979                 ret = -EOPNOTSUPP;
1980                 break;
1981         }
1982         return ret;
1983 }
1984
1985 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
1986 {
1987         int ret = 0;
1988         struct adapter *padapter = rtw_netdev_priv(dev);
1989
1990         switch (command) {
1991         case IEEE_MLME_STA_DEAUTH:
1992                 if (!rtw_set_802_11_disassociate(padapter))
1993                         ret = -1;
1994                 break;
1995         case IEEE_MLME_STA_DISASSOC:
1996                 if (!rtw_set_802_11_disassociate(padapter))
1997                         ret = -1;
1998                 break;
1999         default:
2000                 ret = -EOPNOTSUPP;
2001                 break;
2002         }
2003
2004         return ret;
2005 }
2006
2007 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2008 {
2009         struct ieee_param *param;
2010         uint ret = 0;
2011
2012         if (!p->pointer || p->length != sizeof(struct ieee_param))
2013                 return -EINVAL;
2014
2015         param = memdup_user(p->pointer, p->length);
2016         if (IS_ERR(param))
2017                 return PTR_ERR(param);
2018
2019         switch (param->cmd) {
2020         case IEEE_CMD_SET_WPA_PARAM:
2021                 ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
2022                 break;
2023
2024         case IEEE_CMD_SET_WPA_IE:
2025                 ret =  rtw_set_wpa_ie(rtw_netdev_priv(dev),
2026                                       (char *)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
2027                 break;
2028
2029         case IEEE_CMD_SET_ENCRYPTION:
2030                 ret = wpa_set_encryption(dev, param, p->length);
2031                 break;
2032
2033         case IEEE_CMD_MLME:
2034                 ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
2035                 break;
2036
2037         default:
2038                 DBG_88E("Unknown WPA supplicant request: %d\n", param->cmd);
2039                 ret = -EOPNOTSUPP;
2040                 break;
2041         }
2042
2043         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2044                 ret = -EFAULT;
2045
2046         kfree(param);
2047         return ret;
2048 }
2049
2050 #ifdef CONFIG_88EU_AP_MODE
2051 static u8 set_pairwise_key(struct adapter *padapter, struct sta_info *psta)
2052 {
2053         struct cmd_obj *ph2c;
2054         struct set_stakey_parm  *psetstakey_para;
2055         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2056         u8 res = _SUCCESS;
2057
2058         ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
2059         if (!ph2c) {
2060                 res = _FAIL;
2061                 goto exit;
2062         }
2063
2064         psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
2065         if (!psetstakey_para) {
2066                 kfree(ph2c);
2067                 res = _FAIL;
2068                 goto exit;
2069         }
2070
2071         init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
2072
2073         psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy;
2074
2075         memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);
2076
2077         memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
2078
2079         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
2080
2081 exit:
2082
2083         return res;
2084 }
2085
2086 static int set_group_key(struct adapter *padapter, u8 *key, u8 alg, int keyid)
2087 {
2088         u8 keylen;
2089         struct cmd_obj *pcmd;
2090         struct setkey_parm *psetkeyparm;
2091         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2092         int res = _SUCCESS;
2093
2094         DBG_88E("%s\n", __func__);
2095
2096         pcmd = kzalloc(sizeof(struct    cmd_obj), GFP_KERNEL);
2097         if (!pcmd) {
2098                 res = _FAIL;
2099                 goto exit;
2100         }
2101         psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
2102         if (!psetkeyparm) {
2103                 kfree(pcmd);
2104                 res = _FAIL;
2105                 goto exit;
2106         }
2107
2108         psetkeyparm->keyid = (u8)keyid;
2109
2110         psetkeyparm->algorithm = alg;
2111
2112         psetkeyparm->set_tx = 1;
2113
2114         switch (alg) {
2115         case _WEP40_:
2116                 keylen = 5;
2117                 break;
2118         case _WEP104_:
2119                 keylen = 13;
2120                 break;
2121         case _TKIP_:
2122         case _TKIP_WTMIC_:
2123         case _AES_:
2124         default:
2125                 keylen = 16;
2126         }
2127
2128         memcpy(&psetkeyparm->key[0], key, keylen);
2129
2130         pcmd->cmdcode = _SetKey_CMD_;
2131         pcmd->parmbuf = (u8 *)psetkeyparm;
2132         pcmd->cmdsz =  (sizeof(struct setkey_parm));
2133         pcmd->rsp = NULL;
2134         pcmd->rspsz = 0;
2135
2136         INIT_LIST_HEAD(&pcmd->list);
2137
2138         res = rtw_enqueue_cmd(pcmdpriv, pcmd);
2139
2140 exit:
2141
2142         return res;
2143 }
2144
2145 static int set_wep_key(struct adapter *padapter, u8 *key, u8 keylen, int keyid)
2146 {
2147         u8 alg;
2148
2149         switch (keylen) {
2150         case 5:
2151                 alg = _WEP40_;
2152                 break;
2153         case 13:
2154                 alg = _WEP104_;
2155                 break;
2156         default:
2157                 alg = _NO_PRIVACY_;
2158         }
2159
2160         return set_group_key(padapter, key, alg, keyid);
2161 }
2162
2163 static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
2164 {
2165         int ret = 0;
2166         u32 wep_key_idx, wep_key_len, wep_total_len;
2167         struct ndis_802_11_wep   *pwep = NULL;
2168         struct sta_info *psta = NULL, *pbcmc_sta = NULL;
2169         struct adapter *padapter = rtw_netdev_priv(dev);
2170         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
2171         struct security_priv *psecuritypriv = &padapter->securitypriv;
2172         struct sta_priv *pstapriv = &padapter->stapriv;
2173
2174         DBG_88E("%s\n", __func__);
2175         param->u.crypt.err = 0;
2176         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
2177         if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {
2178                 ret =  -EINVAL;
2179                 goto exit;
2180         }
2181         if (is_broadcast_ether_addr(param->sta_addr)) {
2182                 if (param->u.crypt.idx >= WEP_KEYS) {
2183                         ret = -EINVAL;
2184                         goto exit;
2185                 }
2186         } else {
2187                 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
2188                 if (!psta) {
2189                         DBG_88E("%s(), sta has already been removed or never been added\n", __func__);
2190                         goto exit;
2191                 }
2192         }
2193
2194         if (strcmp(param->u.crypt.alg, "none") == 0 && (!psta)) {
2195                 /* todo:clear default encryption keys */
2196
2197                 DBG_88E("clear default encryption keys, keyid =%d\n", param->u.crypt.idx);
2198                 goto exit;
2199         }
2200         if (strcmp(param->u.crypt.alg, "WEP") == 0 && (!psta)) {
2201                 DBG_88E("r871x_set_encryption, crypt.alg = WEP\n");
2202                 wep_key_idx = param->u.crypt.idx;
2203                 wep_key_len = param->u.crypt.key_len;
2204                 DBG_88E("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);
2205                 if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
2206                         ret = -EINVAL;
2207                         goto exit;
2208                 }
2209
2210                 if (wep_key_len > 0) {
2211                         wep_key_len = wep_key_len <= 5 ? 5 : 13;
2212                         wep_total_len = wep_key_len + offsetof(struct ndis_802_11_wep, KeyMaterial);
2213                         pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len);
2214                         if (!pwep) {
2215                                 DBG_88E(" r871x_set_encryption: pwep allocate fail !!!\n");
2216                                 goto exit;
2217                         }
2218
2219                         memset(pwep, 0, wep_total_len);
2220
2221                         pwep->KeyLength = wep_key_len;
2222                         pwep->Length = wep_total_len;
2223                 }
2224
2225                 pwep->KeyIndex = wep_key_idx;
2226
2227                 memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
2228
2229                 if (param->u.crypt.set_tx) {
2230                         DBG_88E("wep, set_tx = 1\n");
2231
2232                         psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
2233                         psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
2234                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
2235
2236                         if (pwep->KeyLength == 13) {
2237                                 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
2238                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
2239                         }
2240
2241                         psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
2242
2243                         memcpy(&psecuritypriv->dot11DefKey[wep_key_idx].skey[0], pwep->KeyMaterial, pwep->KeyLength);
2244
2245                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
2246
2247                         set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
2248                 } else {
2249                         DBG_88E("wep, set_tx = 0\n");
2250
2251                         /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
2252                         /* psecuritypriv->dot11PrivacyKeyIndex = keyid", but can rtw_set_key to cam */
2253
2254                         memcpy(&psecuritypriv->dot11DefKey[wep_key_idx].skey[0], pwep->KeyMaterial, pwep->KeyLength);
2255
2256                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
2257
2258                         set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
2259                 }
2260
2261                 goto exit;
2262         }
2263
2264         if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /*  group key */
2265                 if (param->u.crypt.set_tx == 1) {
2266                         if (strcmp(param->u.crypt.alg, "WEP") == 0) {
2267                                 DBG_88E("%s, set group_key, WEP\n", __func__);
2268
2269                                 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2270                                        param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
2271
2272                                 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
2273                                 if (param->u.crypt.key_len == 13)
2274                                         psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
2275                         } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
2276                                 DBG_88E("%s, set group_key, TKIP\n", __func__);
2277                                 psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
2278                                 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2279                                        param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
2280                                 /* set mic key */
2281                                 memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[16], 8);
2282                                 memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[24], 8);
2283
2284                                 psecuritypriv->busetkipkey = true;
2285                         } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
2286                                 DBG_88E("%s, set group_key, CCMP\n", __func__);
2287                                 psecuritypriv->dot118021XGrpPrivacy = _AES_;
2288                                 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2289                                        param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
2290                         } else {
2291                                 DBG_88E("%s, set group_key, none\n", __func__);
2292                                 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
2293                         }
2294                         psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
2295                         psecuritypriv->binstallGrpkey = true;
2296                         psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
2297                         set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
2298                         pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
2299                         if (pbcmc_sta) {
2300                                 pbcmc_sta->ieee8021x_blocked = false;
2301                                 pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
2302                         }
2303                 }
2304                 goto exit;
2305         }
2306
2307         if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /*  psk/802_1x */
2308                 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
2309                         if (param->u.crypt.set_tx == 1) {
2310                                 memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
2311
2312                                 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
2313                                         DBG_88E("%s, set pairwise key, WEP\n", __func__);
2314
2315                                         psta->dot118021XPrivacy = _WEP40_;
2316                                         if (param->u.crypt.key_len == 13)
2317                                                 psta->dot118021XPrivacy = _WEP104_;
2318                                 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
2319                                         DBG_88E("%s, set pairwise key, TKIP\n", __func__);
2320
2321                                         psta->dot118021XPrivacy = _TKIP_;
2322
2323                                         /* set mic key */
2324                                         memcpy(psta->dot11tkiptxmickey.skey, &param->u.crypt.key[16], 8);
2325                                         memcpy(psta->dot11tkiprxmickey.skey, &param->u.crypt.key[24], 8);
2326
2327                                         psecuritypriv->busetkipkey = true;
2328                                 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
2329                                         DBG_88E("%s, set pairwise key, CCMP\n", __func__);
2330
2331                                         psta->dot118021XPrivacy = _AES_;
2332                                 } else {
2333                                         DBG_88E("%s, set pairwise key, none\n", __func__);
2334
2335                                         psta->dot118021XPrivacy = _NO_PRIVACY_;
2336                                 }
2337
2338                                 set_pairwise_key(padapter, psta);
2339
2340                                 psta->ieee8021x_blocked = false;
2341                         } else { /* group key??? */
2342                                 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
2343                                         memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2344                                                param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
2345                                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
2346                                         if (param->u.crypt.key_len == 13)
2347                                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
2348                                 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
2349                                         psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
2350
2351                                         memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2352                                                param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
2353
2354                                         /* set mic key */
2355                                         memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[16], 8);
2356                                         memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[24], 8);
2357
2358                                         psecuritypriv->busetkipkey = true;
2359                                 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
2360                                         psecuritypriv->dot118021XGrpPrivacy = _AES_;
2361
2362                                         memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2363                                                param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
2364                                 } else {
2365                                         psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
2366                                 }
2367
2368                                 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
2369
2370                                 psecuritypriv->binstallGrpkey = true;
2371
2372                                 psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
2373
2374                                 set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
2375
2376                                 pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
2377                                 if (pbcmc_sta) {
2378                                         pbcmc_sta->ieee8021x_blocked = false;
2379                                         pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
2380                                 }
2381                         }
2382                 }
2383         }
2384
2385 exit:
2386
2387         kfree(pwep);
2388
2389         return ret;
2390 }
2391
2392 static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
2393 {
2394         int ret = 0;
2395         struct adapter *padapter = rtw_netdev_priv(dev);
2396         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2397         struct sta_priv *pstapriv = &padapter->stapriv;
2398         unsigned char *pbuf = param->u.bcn_ie.buf;
2399
2400         DBG_88E("%s, len =%d\n", __func__, len);
2401
2402         if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
2403                 return -EINVAL;
2404
2405         memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
2406
2407         if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
2408                 pstapriv->max_num_sta = NUM_STA;
2409
2410         if (rtw_check_beacon_data(padapter, pbuf, len - 12 - 2) == _SUCCESS) /* 12 = param header, 2:no packed */
2411                 ret = 0;
2412         else
2413                 ret = -EINVAL;
2414
2415         return ret;
2416 }
2417
2418 static int rtw_hostapd_sta_flush(struct net_device *dev)
2419 {
2420         struct adapter *padapter = rtw_netdev_priv(dev);
2421
2422         DBG_88E("%s\n", __func__);
2423
2424         flush_all_cam_entry(padapter);  /* clear CAM */
2425
2426         return rtw_sta_flush(padapter);
2427 }
2428
2429 static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
2430 {
2431         int ret = 0;
2432         struct sta_info *psta = NULL;
2433         struct adapter *padapter = rtw_netdev_priv(dev);
2434         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2435         struct sta_priv *pstapriv = &padapter->stapriv;
2436
2437         DBG_88E("%s(aid =%d) =%pM\n", __func__, param->u.add_sta.aid, (param->sta_addr));
2438
2439         if (!check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)))
2440                 return -EINVAL;
2441
2442         if (is_broadcast_ether_addr(param->sta_addr))
2443                 return -EINVAL;
2444
2445         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
2446         if (psta) {
2447                 int flags = param->u.add_sta.flags;
2448
2449                 psta->aid = param->u.add_sta.aid;/* aid = 1~2007 */
2450
2451                 memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
2452
2453                 /* check wmm cap. */
2454                 if (WLAN_STA_WME & flags)
2455                         psta->qos_option = 1;
2456                 else
2457                         psta->qos_option = 0;
2458
2459                 if (pmlmepriv->qospriv.qos_option == 0)
2460                         psta->qos_option = 0;
2461
2462                 /* chec 802.11n ht cap. */
2463                 if (WLAN_STA_HT & flags) {
2464                         psta->htpriv.ht_option = true;
2465                         psta->qos_option = 1;
2466                         memcpy(&psta->htpriv.ht_cap, &param->u.add_sta.ht_cap,
2467                                sizeof(struct ieee80211_ht_cap));
2468                 } else {
2469                         psta->htpriv.ht_option = false;
2470                 }
2471
2472                 if (!pmlmepriv->htpriv.ht_option)
2473                         psta->htpriv.ht_option = false;
2474
2475                 update_sta_info_apmode(padapter, psta);
2476         } else {
2477                 ret = -ENOMEM;
2478         }
2479
2480         return ret;
2481 }
2482
2483 static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
2484 {
2485         struct sta_info *psta = NULL;
2486         struct adapter *padapter = rtw_netdev_priv(dev);
2487         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2488         struct sta_priv *pstapriv = &padapter->stapriv;
2489         int updated = 0;
2490
2491         DBG_88E("%s =%pM\n", __func__, (param->sta_addr));
2492
2493         if (!check_fwstate(pmlmepriv, _FW_LINKED | WIFI_AP_STATE))
2494                 return -EINVAL;
2495
2496         if (is_broadcast_ether_addr(param->sta_addr))
2497                 return -EINVAL;
2498
2499         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
2500         if (psta) {
2501                 spin_lock_bh(&pstapriv->asoc_list_lock);
2502                 if (!list_empty(&psta->asoc_list)) {
2503                         list_del_init(&psta->asoc_list);
2504                         pstapriv->asoc_list_cnt--;
2505                         updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
2506                 }
2507                 spin_unlock_bh(&pstapriv->asoc_list_lock);
2508                 associated_clients_update(padapter, updated);
2509                 psta = NULL;
2510         } else {
2511                 DBG_88E("%s(), sta has already been removed or never been added\n", __func__);
2512         }
2513
2514         return 0;
2515 }
2516
2517 static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
2518 {
2519         int ret = 0;
2520         struct sta_info *psta = NULL;
2521         struct adapter *padapter = rtw_netdev_priv(dev);
2522         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2523         struct sta_priv *pstapriv = &padapter->stapriv;
2524         struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
2525         struct sta_data *psta_data = (struct sta_data *)param_ex->data;
2526
2527         DBG_88E("rtw_ioctl_get_sta_info, sta_addr: %pM\n", (param_ex->sta_addr));
2528
2529         if (!check_fwstate(pmlmepriv, _FW_LINKED | WIFI_AP_STATE))
2530                 return -EINVAL;
2531
2532         if (is_broadcast_ether_addr(param_ex->sta_addr))
2533                 return -EINVAL;
2534
2535         psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
2536         if (psta) {
2537                 psta_data->aid = (u16)psta->aid;
2538                 psta_data->capability = psta->capability;
2539                 psta_data->flags = psta->flags;
2540
2541 /*
2542                 nonerp_set : BIT(0)
2543                 no_short_slot_time_set : BIT(1)
2544                 no_short_preamble_set : BIT(2)
2545                 no_ht_gf_set : BIT(3)
2546                 no_ht_set : BIT(4)
2547                 ht_20mhz_set : BIT(5)
2548 */
2549
2550                 psta_data->sta_set = ((psta->nonerp_set) |
2551                                       (psta->no_short_slot_time_set << 1) |
2552                                       (psta->no_short_preamble_set << 2) |
2553                                       (psta->no_ht_gf_set << 3) |
2554                                       (psta->no_ht_set << 4) |
2555                                       (psta->ht_20mhz_set << 5));
2556                 psta_data->tx_supp_rates_len =  psta->bssratelen;
2557                 memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
2558                 memcpy(&psta_data->ht_cap,
2559                        &psta->htpriv.ht_cap, sizeof(struct ieee80211_ht_cap));
2560                 psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
2561                 psta_data->rx_bytes = psta->sta_stats.rx_bytes;
2562                 psta_data->rx_drops = psta->sta_stats.rx_drops;
2563                 psta_data->tx_pkts = psta->sta_stats.tx_pkts;
2564                 psta_data->tx_bytes = psta->sta_stats.tx_bytes;
2565                 psta_data->tx_drops = psta->sta_stats.tx_drops;
2566         } else {
2567                 ret = -1;
2568         }
2569
2570         return ret;
2571 }
2572
2573 static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
2574 {
2575         int ret = 0;
2576         struct sta_info *psta = NULL;
2577         struct adapter *padapter = rtw_netdev_priv(dev);
2578         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2579         struct sta_priv *pstapriv = &padapter->stapriv;
2580
2581         DBG_88E("%s, sta_addr: %pM\n", __func__, (param->sta_addr));
2582
2583         if (!check_fwstate(pmlmepriv, _FW_LINKED | WIFI_AP_STATE))
2584                 return -EINVAL;
2585
2586         if (is_broadcast_ether_addr(param->sta_addr))
2587                 return -EINVAL;
2588
2589         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
2590         if (psta) {
2591                 if (psta->wpa_ie[0] == WLAN_EID_RSN ||
2592                     psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
2593                         int wpa_ie_len;
2594                         int copy_len;
2595
2596                         wpa_ie_len = psta->wpa_ie[1];
2597                         copy_len = min_t(int, wpa_ie_len + 2, sizeof(psta->wpa_ie));
2598                         param->u.wpa_ie.len = copy_len;
2599                         memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
2600                 } else {
2601                         DBG_88E("sta's wpa_ie is NONE\n");
2602                 }
2603         } else {
2604                 ret = -1;
2605         }
2606
2607         return ret;
2608 }
2609
2610 static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
2611 {
2612         unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
2613         struct adapter *padapter = rtw_netdev_priv(dev);
2614         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2615         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2616         int ie_len;
2617
2618         DBG_88E("%s, len =%d\n", __func__, len);
2619
2620         if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
2621                 return -EINVAL;
2622
2623         ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */
2624
2625         kfree(pmlmepriv->wps_beacon_ie);
2626         pmlmepriv->wps_beacon_ie = NULL;
2627
2628         if (ie_len > 0) {
2629                 pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
2630                 pmlmepriv->wps_beacon_ie_len = ie_len;
2631                 if (!pmlmepriv->wps_beacon_ie) {
2632                         DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
2633                         return -EINVAL;
2634                 }
2635
2636                 memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
2637
2638                 update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
2639
2640                 pmlmeext->bstart_bss = true;
2641         }
2642
2643         return 0;
2644 }
2645
2646 static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
2647 {
2648         struct adapter *padapter = rtw_netdev_priv(dev);
2649         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2650         int ie_len;
2651
2652         DBG_88E("%s, len =%d\n", __func__, len);
2653
2654         if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
2655                 return -EINVAL;
2656
2657         ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */
2658
2659         kfree(pmlmepriv->wps_probe_resp_ie);
2660         pmlmepriv->wps_probe_resp_ie = NULL;
2661
2662         if (ie_len > 0) {
2663                 pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
2664                 pmlmepriv->wps_probe_resp_ie_len = ie_len;
2665                 if (!pmlmepriv->wps_probe_resp_ie) {
2666                         DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
2667                         return -EINVAL;
2668                 }
2669                 memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
2670         }
2671
2672         return 0;
2673 }
2674
2675 static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
2676 {
2677         struct adapter *padapter = rtw_netdev_priv(dev);
2678         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2679         int ie_len;
2680
2681         DBG_88E("%s, len =%d\n", __func__, len);
2682
2683         if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
2684                 return -EINVAL;
2685
2686         ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */
2687
2688         kfree(pmlmepriv->wps_assoc_resp_ie);
2689         pmlmepriv->wps_assoc_resp_ie = NULL;
2690
2691         if (ie_len > 0) {
2692                 pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
2693                 pmlmepriv->wps_assoc_resp_ie_len = ie_len;
2694                 if (!pmlmepriv->wps_assoc_resp_ie) {
2695                         DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
2696                         return -EINVAL;
2697                 }
2698
2699                 memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
2700         }
2701
2702         return 0;
2703 }
2704
2705 static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
2706 {
2707         struct adapter *padapter = rtw_netdev_priv(dev);
2708         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2709         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2710         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2711
2712         u8 value;
2713
2714         if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
2715                 return -EINVAL;
2716
2717         if (param->u.wpa_param.name != 0) /* dummy test... */
2718                 DBG_88E("%s name(%u) != 0\n", __func__, param->u.wpa_param.name);
2719         value = param->u.wpa_param.value;
2720
2721         /* use the same definition of hostapd's ignore_broadcast_ssid */
2722         if (value != 1 && value != 2)
2723                 value = 0;
2724         DBG_88E("%s value(%u)\n", __func__, value);
2725         pmlmeinfo->hidden_ssid_mode = value;
2726         return 0;
2727 }
2728
2729 static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
2730 {
2731         struct adapter *padapter = rtw_netdev_priv(dev);
2732         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2733
2734         if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
2735                 return -EINVAL;
2736
2737         if (is_broadcast_ether_addr(param->sta_addr))
2738                 return -EINVAL;
2739
2740         return rtw_acl_remove_sta(padapter, param->sta_addr);
2741 }
2742
2743 static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
2744 {
2745         struct adapter *padapter = rtw_netdev_priv(dev);
2746         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2747
2748         if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
2749                 return -EINVAL;
2750
2751         if (is_broadcast_ether_addr(param->sta_addr))
2752                 return -EINVAL;
2753
2754         return rtw_acl_add_sta(padapter, param->sta_addr);
2755 }
2756
2757 static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
2758 {
2759         struct adapter *padapter = rtw_netdev_priv(dev);
2760         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2761
2762         if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
2763                 return -EINVAL;
2764
2765         rtw_set_macaddr_acl(padapter, param->u.mlme.command);
2766
2767         return 0;
2768 }
2769
2770 static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
2771 {
2772         struct ieee_param *param;
2773         int ret = 0;
2774         struct adapter *padapter = rtw_netdev_priv(dev);
2775
2776         /*
2777          * this function is expect to call in master mode, which allows no power saving
2778          * so, we just check hw_init_completed
2779          */
2780
2781         if (!padapter->hw_init_completed)
2782                 return -EPERM;
2783
2784         if (!p->pointer || p->length != sizeof(struct ieee_param))
2785                 return -EINVAL;
2786
2787         param = memdup_user(p->pointer, p->length);
2788         if (IS_ERR(param))
2789                 return PTR_ERR(param);
2790
2791         switch (param->cmd) {
2792         case RTL871X_HOSTAPD_FLUSH:
2793                 ret = rtw_hostapd_sta_flush(dev);
2794                 break;
2795         case RTL871X_HOSTAPD_ADD_STA:
2796                 ret = rtw_add_sta(dev, param);
2797                 break;
2798         case RTL871X_HOSTAPD_REMOVE_STA:
2799                 ret = rtw_del_sta(dev, param);
2800                 break;
2801         case RTL871X_HOSTAPD_SET_BEACON:
2802                 ret = rtw_set_beacon(dev, param, p->length);
2803                 break;
2804         case RTL871X_SET_ENCRYPTION:
2805                 ret = rtw_set_encryption(dev, param, p->length);
2806                 break;
2807         case RTL871X_HOSTAPD_GET_WPAIE_STA:
2808                 ret = rtw_get_sta_wpaie(dev, param);
2809                 break;
2810         case RTL871X_HOSTAPD_SET_WPS_BEACON:
2811                 ret = rtw_set_wps_beacon(dev, param, p->length);
2812                 break;
2813         case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
2814                 ret = rtw_set_wps_probe_resp(dev, param, p->length);
2815                 break;
2816         case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
2817                 ret = rtw_set_wps_assoc_resp(dev, param, p->length);
2818                 break;
2819         case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
2820                 ret = rtw_set_hidden_ssid(dev, param, p->length);
2821                 break;
2822         case RTL871X_HOSTAPD_GET_INFO_STA:
2823                 ret = rtw_ioctl_get_sta_data(dev, param, p->length);
2824                 break;
2825         case RTL871X_HOSTAPD_SET_MACADDR_ACL:
2826                 ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
2827                 break;
2828         case RTL871X_HOSTAPD_ACL_ADD_STA:
2829                 ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
2830                 break;
2831         case RTL871X_HOSTAPD_ACL_REMOVE_STA:
2832                 ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
2833                 break;
2834         default:
2835                 DBG_88E("Unknown hostapd request: %d\n", param->cmd);
2836                 ret = -EOPNOTSUPP;
2837                 break;
2838         }
2839
2840         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2841                 ret = -EFAULT;
2842         kfree(param);
2843         return ret;
2844 }
2845 #endif
2846
2847 #include <rtw_android.h>
2848 static int rtw_wx_set_priv(struct net_device *dev,
2849                            struct iw_request_info *info,
2850                            union iwreq_data *awrq, char *extra)
2851 {
2852         int ret = 0;
2853         int len = 0;
2854         char *ext;
2855         struct adapter *padapter = rtw_netdev_priv(dev);
2856         struct iw_point *dwrq = (struct iw_point *)awrq;
2857
2858         if (dwrq->length == 0)
2859                 return -EFAULT;
2860
2861         len = dwrq->length;
2862         ext = vmalloc(len);
2863         if (!ext)
2864                 return -ENOMEM;
2865
2866         if (copy_from_user(ext, dwrq->pointer, len)) {
2867                 vfree(ext);
2868                 return -EFAULT;
2869         }
2870
2871         /* added for wps2.0 @20110524 */
2872         if (dwrq->flags == 0x8766 && len > 8) {
2873                 u32 cp_sz;
2874                 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2875                 u8 *probereq_wpsie = ext;
2876                 int probereq_wpsie_len = len;
2877                 u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
2878
2879                 if ((probereq_wpsie[0] == _VENDOR_SPECIFIC_IE_) &&
2880                     (!memcmp(&probereq_wpsie[2], wps_oui, 4))) {
2881                         cp_sz = min(probereq_wpsie_len, MAX_WPS_IE_LEN);
2882
2883                         pmlmepriv->wps_probe_req_ie_len = 0;
2884                         kfree(pmlmepriv->wps_probe_req_ie);
2885                         pmlmepriv->wps_probe_req_ie = NULL;
2886
2887                         pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz);
2888                         if (!pmlmepriv->wps_probe_req_ie) {
2889                                 pr_info("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
2890                                 ret =  -EINVAL;
2891                                 goto FREE_EXT;
2892                         }
2893                         memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
2894                         pmlmepriv->wps_probe_req_ie_len = cp_sz;
2895                 }
2896                 goto FREE_EXT;
2897         }
2898
2899         if (len >= WEXT_CSCAN_HEADER_SIZE &&
2900             !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
2901                 ret = rtw_wx_set_scan(dev, info, awrq, ext);
2902                 goto FREE_EXT;
2903         }
2904
2905 FREE_EXT:
2906
2907         vfree(ext);
2908
2909         return ret;
2910 }
2911
2912 static iw_handler rtw_handlers[] = {
2913         NULL,                                   /* SIOCSIWCOMMIT */
2914         rtw_wx_get_name,                /* SIOCGIWNAME */
2915         dummy,                                  /* SIOCSIWNWID */
2916         dummy,                                  /* SIOCGIWNWID */
2917         rtw_wx_set_freq,                /* SIOCSIWFREQ */
2918         rtw_wx_get_freq,                /* SIOCGIWFREQ */
2919         rtw_wx_set_mode,                /* SIOCSIWMODE */
2920         rtw_wx_get_mode,                /* SIOCGIWMODE */
2921         dummy,                                  /* SIOCSIWSENS */
2922         rtw_wx_get_sens,                /* SIOCGIWSENS */
2923         NULL,                                   /* SIOCSIWRANGE */
2924         rtw_wx_get_range,               /* SIOCGIWRANGE */
2925         rtw_wx_set_priv,                /* SIOCSIWPRIV */
2926         NULL,                                   /* SIOCGIWPRIV */
2927         NULL,                                   /* SIOCSIWSTATS */
2928         NULL,                                   /* SIOCGIWSTATS */
2929         dummy,                                  /* SIOCSIWSPY */
2930         dummy,                                  /* SIOCGIWSPY */
2931         NULL,                                   /* SIOCGIWTHRSPY */
2932         NULL,                                   /* SIOCWIWTHRSPY */
2933         rtw_wx_set_wap,         /* SIOCSIWAP */
2934         rtw_wx_get_wap,         /* SIOCGIWAP */
2935         rtw_wx_set_mlme,                /* request MLME operation; uses struct iw_mlme */
2936         dummy,                                  /* SIOCGIWAPLIST -- depricated */
2937         rtw_wx_set_scan,                /* SIOCSIWSCAN */
2938         rtw_wx_get_scan,                /* SIOCGIWSCAN */
2939         rtw_wx_set_essid,               /* SIOCSIWESSID */
2940         rtw_wx_get_essid,               /* SIOCGIWESSID */
2941         dummy,                                  /* SIOCSIWNICKN */
2942         rtw_wx_get_nick,                /* SIOCGIWNICKN */
2943         NULL,                                   /* -- hole -- */
2944         NULL,                                   /* -- hole -- */
2945         rtw_wx_set_rate,                /* SIOCSIWRATE */
2946         rtw_wx_get_rate,                /* SIOCGIWRATE */
2947         rtw_wx_set_rts,                 /* SIOCSIWRTS */
2948         rtw_wx_get_rts,                 /* SIOCGIWRTS */
2949         rtw_wx_set_frag,                /* SIOCSIWFRAG */
2950         rtw_wx_get_frag,                /* SIOCGIWFRAG */
2951         dummy,                                  /* SIOCSIWTXPOW */
2952         dummy,                                  /* SIOCGIWTXPOW */
2953         dummy,                                  /* SIOCSIWRETRY */
2954         rtw_wx_get_retry,               /* SIOCGIWRETRY */
2955         rtw_wx_set_enc,                 /* SIOCSIWENCODE */
2956         rtw_wx_get_enc,                 /* SIOCGIWENCODE */
2957         dummy,                                  /* SIOCSIWPOWER */
2958         rtw_wx_get_power,               /* SIOCGIWPOWER */
2959         NULL,                                   /*---hole---*/
2960         NULL,                                   /*---hole---*/
2961         rtw_wx_set_gen_ie,              /* SIOCSIWGENIE */
2962         NULL,                                   /* SIOCGWGENIE */
2963         rtw_wx_set_auth,                /* SIOCSIWAUTH */
2964         NULL,                                   /* SIOCGIWAUTH */
2965         rtw_wx_set_enc_ext,             /* SIOCSIWENCODEEXT */
2966         NULL,                                   /* SIOCGIWENCODEEXT */
2967         rtw_wx_set_pmkid,               /* SIOCSIWPMKSA */
2968         NULL,                                   /*---hole---*/
2969 };
2970
2971 static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
2972 {
2973         struct adapter *padapter = rtw_netdev_priv(dev);
2974         struct iw_statistics *piwstats = &padapter->iwstats;
2975         int tmp_level = 0;
2976         int tmp_qual = 0;
2977         int tmp_noise = 0;
2978
2979         if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
2980                 piwstats->qual.qual = 0;
2981                 piwstats->qual.level = 0;
2982                 piwstats->qual.noise = 0;
2983         } else {
2984                 tmp_level = padapter->recvpriv.signal_strength;
2985                 tmp_qual = padapter->recvpriv.signal_qual;
2986                 tmp_noise = padapter->recvpriv.noise;
2987
2988                 piwstats->qual.level = tmp_level;
2989                 piwstats->qual.qual = tmp_qual;
2990                 piwstats->qual.noise = tmp_noise;
2991         }
2992         piwstats->qual.updated = IW_QUAL_ALL_UPDATED;/* IW_QUAL_DBM; */
2993         return &padapter->iwstats;
2994 }
2995
2996 struct iw_handler_def rtw_handlers_def = {
2997         .standard = rtw_handlers,
2998         .num_standard = ARRAY_SIZE(rtw_handlers),
2999         .get_wireless_stats = rtw_get_wireless_stats,
3000 };
3001
3002 int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
3003 {
3004         struct iwreq *wrq = (struct iwreq *)rq;
3005         int ret = 0;
3006
3007         switch (cmd) {
3008         case RTL_IOCTL_WPA_SUPPLICANT:
3009                 ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
3010                 break;
3011 #ifdef CONFIG_88EU_AP_MODE
3012         case RTL_IOCTL_HOSTAPD:
3013                 ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
3014                 break;
3015 #endif /*  CONFIG_88EU_AP_MODE */
3016         case (SIOCDEVPRIVATE + 1):
3017                 ret = rtw_android_priv_cmd(dev, rq, cmd);
3018                 break;
3019         default:
3020                 ret = -EOPNOTSUPP;
3021                 break;
3022         }
3023         return ret;
3024 }