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