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