158391efdSNathan Chancellor // SPDX-License-Identifier: GPL-2.0
2554c0a3aSHans de Goede /******************************************************************************
3554c0a3aSHans de Goede  *
4554c0a3aSHans de Goede  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5554c0a3aSHans de Goede  *
6554c0a3aSHans de Goede  ******************************************************************************/
7554c0a3aSHans de Goede 
82dcce8edSArushi Singhal #include <linux/etherdevice.h>
9554c0a3aSHans de Goede #include <drv_types.h>
10554c0a3aSHans de Goede #include <rtw_debug.h>
11554c0a3aSHans de Goede #include <rtw_mp.h>
127d6a6e7bSNishka Dasgupta #include <hal_btcoex.h>
13554c0a3aSHans de Goede #include <linux/jiffies.h>
1460db8d10SJérémy Lefaure #include <linux/kernel.h>
15554c0a3aSHans de Goede 
16f85ac230STeo Dacquet #define RTL_IOCTL_WPA_SUPPLICANT	(SIOCIWFIRSTPRIV + 30)
17554c0a3aSHans de Goede 
wpa_set_auth_algs(struct net_device * dev,u32 value)18554c0a3aSHans de Goede static int wpa_set_auth_algs(struct net_device *dev, u32 value)
19554c0a3aSHans de Goede {
2042a18f09SIvan Safonov 	struct adapter *padapter = rtw_netdev_priv(dev);
21554c0a3aSHans de Goede 	int ret = 0;
22554c0a3aSHans de Goede 
23b658acbfSFabio Aiuto 	if ((value & IW_AUTH_ALG_SHARED_KEY) && (value & IW_AUTH_ALG_OPEN_SYSTEM)) {
24554c0a3aSHans de Goede 		padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
25554c0a3aSHans de Goede 		padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
26554c0a3aSHans de Goede 		padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
27b658acbfSFabio Aiuto 	} else if (value & IW_AUTH_ALG_SHARED_KEY)	{
28554c0a3aSHans de Goede 		padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
29554c0a3aSHans de Goede 
30554c0a3aSHans de Goede 		padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
31554c0a3aSHans de Goede 		padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
32b658acbfSFabio Aiuto 	} else if (value & IW_AUTH_ALG_OPEN_SYSTEM) {
33554c0a3aSHans de Goede 		/* padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; */
34f85ac230STeo Dacquet 		if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
35554c0a3aSHans de Goede 			padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
36554c0a3aSHans de Goede 			padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
37554c0a3aSHans de Goede 		}
38f85ac230STeo Dacquet 	} else {
39554c0a3aSHans de Goede 		ret = -EINVAL;
40554c0a3aSHans de Goede 	}
41554c0a3aSHans de Goede 
42554c0a3aSHans de Goede 	return ret;
43554c0a3aSHans de Goede }
44554c0a3aSHans de Goede 
wpa_set_encryption(struct net_device * dev,struct ieee_param * param,u32 param_len)45554c0a3aSHans de Goede static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
46554c0a3aSHans de Goede {
47554c0a3aSHans de Goede 	int ret = 0;
4805cbcc41SHans de Goede 	u8 max_idx;
49554c0a3aSHans de Goede 	u32 wep_key_idx, wep_key_len, wep_total_len;
50554c0a3aSHans de Goede 	struct ndis_802_11_wep	 *pwep = NULL;
5142a18f09SIvan Safonov 	struct adapter *padapter = rtw_netdev_priv(dev);
52554c0a3aSHans de Goede 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
53554c0a3aSHans de Goede 	struct security_priv *psecuritypriv = &padapter->securitypriv;
54554c0a3aSHans de Goede 
55554c0a3aSHans de Goede 	param->u.crypt.err = 0;
56554c0a3aSHans de Goede 	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
57554c0a3aSHans de Goede 
58f85ac230STeo Dacquet 	if (param_len < (u32)((u8 *)param->u.crypt.key - (u8 *)param) + param->u.crypt.key_len) {
59554c0a3aSHans de Goede 		ret =  -EINVAL;
60554c0a3aSHans de Goede 		goto exit;
61554c0a3aSHans de Goede 	}
62554c0a3aSHans de Goede 
6305cbcc41SHans de Goede 	if (param->sta_addr[0] != 0xff || param->sta_addr[1] != 0xff ||
6405cbcc41SHans de Goede 	    param->sta_addr[2] != 0xff || param->sta_addr[3] != 0xff ||
6505cbcc41SHans de Goede 	    param->sta_addr[4] != 0xff || param->sta_addr[5] != 0xff) {
66554c0a3aSHans de Goede 		ret = -EINVAL;
67554c0a3aSHans de Goede 		goto exit;
68554c0a3aSHans de Goede 	}
6905cbcc41SHans de Goede 
7005cbcc41SHans de Goede 	if (strcmp(param->u.crypt.alg, "WEP") == 0)
7105cbcc41SHans de Goede 		max_idx = WEP_KEYS - 1;
7205cbcc41SHans de Goede 	else
7305cbcc41SHans de Goede 		max_idx = BIP_MAX_KEYID;
7405cbcc41SHans de Goede 
7505cbcc41SHans de Goede 	if (param->u.crypt.idx > max_idx) {
7605cbcc41SHans de Goede 		netdev_err(dev, "Error crypt.idx %d > %d\n", param->u.crypt.idx, max_idx);
77554c0a3aSHans de Goede 		ret = -EINVAL;
78554c0a3aSHans de Goede 		goto exit;
79554c0a3aSHans de Goede 	}
80554c0a3aSHans de Goede 
81f85ac230STeo Dacquet 	if (strcmp(param->u.crypt.alg, "WEP") == 0) {
82554c0a3aSHans de Goede 		padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
83554c0a3aSHans de Goede 		padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
84554c0a3aSHans de Goede 		padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
85554c0a3aSHans de Goede 
86554c0a3aSHans de Goede 		wep_key_idx = param->u.crypt.idx;
87554c0a3aSHans de Goede 		wep_key_len = param->u.crypt.key_len;
88554c0a3aSHans de Goede 
89f85ac230STeo Dacquet 		if (wep_key_len > 0) {
90554c0a3aSHans de Goede 			wep_key_len = wep_key_len <= 5 ? 5 : 13;
91f133717eSFabio Aiuto 			wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, key_material);
9267ea0a2aSKees Cook 			/* Allocate a full structure to avoid potentially running off the end. */
9367ea0a2aSKees Cook 			pwep = kzalloc(sizeof(*pwep), GFP_KERNEL);
94eb64c6f6SChristophe JAILLET 			if (!pwep) {
95eb64c6f6SChristophe JAILLET 				ret = -ENOMEM;
96554c0a3aSHans de Goede 				goto exit;
97eb64c6f6SChristophe JAILLET 			}
98554c0a3aSHans de Goede 
99f133717eSFabio Aiuto 			pwep->key_length = wep_key_len;
100f133717eSFabio Aiuto 			pwep->length = wep_total_len;
101554c0a3aSHans de Goede 
102f85ac230STeo Dacquet 			if (wep_key_len == 13) {
103554c0a3aSHans de Goede 				padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
104554c0a3aSHans de Goede 				padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
105554c0a3aSHans de Goede 			}
106f85ac230STeo Dacquet 		} else {
107554c0a3aSHans de Goede 			ret = -EINVAL;
108554c0a3aSHans de Goede 			goto exit;
109554c0a3aSHans de Goede 		}
110554c0a3aSHans de Goede 
111f133717eSFabio Aiuto 		pwep->key_index = wep_key_idx;
112f133717eSFabio Aiuto 		pwep->key_index |= 0x80000000;
113554c0a3aSHans de Goede 
114f133717eSFabio Aiuto 		memcpy(pwep->key_material,  param->u.crypt.key, pwep->key_length);
115554c0a3aSHans de Goede 
116f85ac230STeo Dacquet 		if (param->u.crypt.set_tx) {
117554c0a3aSHans de Goede 			if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
118554c0a3aSHans de Goede 				ret = -EOPNOTSUPP;
119f85ac230STeo Dacquet 		} else {
120554c0a3aSHans de Goede 			/* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
121554c0a3aSHans de Goede 			/* psecuritypriv->dot11PrivacyKeyIndex =keyid", but can rtw_set_key to fw/cam */
122554c0a3aSHans de Goede 
123554c0a3aSHans de Goede 			if (wep_key_idx >= WEP_KEYS) {
124554c0a3aSHans de Goede 				ret = -EOPNOTSUPP;
125554c0a3aSHans de Goede 				goto exit;
126554c0a3aSHans de Goede 			}
127554c0a3aSHans de Goede 
128722a3291SFranziska Naepelt 			memcpy(&psecuritypriv->dot11DefKey[wep_key_idx].skey[0], pwep->key_material, pwep->key_length);
129f133717eSFabio Aiuto 			psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->key_length;
130554c0a3aSHans de Goede 			rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0, true);
131554c0a3aSHans de Goede 		}
132554c0a3aSHans de Goede 
133554c0a3aSHans de Goede 		goto exit;
134554c0a3aSHans de Goede 	}
135554c0a3aSHans de Goede 
136f85ac230STeo Dacquet 	if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /*  802_1x */
137554c0a3aSHans de Goede 		struct sta_info *psta, *pbcmc_sta;
138554c0a3aSHans de Goede 		struct sta_priv *pstapriv = &padapter->stapriv;
139554c0a3aSHans de Goede 
140f85ac230STeo Dacquet 		if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == true) { /* sta mode */
141554c0a3aSHans de Goede 			psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
142cd1f1450SMichael Straube 			if (!psta) {
143554c0a3aSHans de Goede 				/* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
144f85ac230STeo Dacquet 			} else {
145554c0a3aSHans de Goede 				/* Jeff: don't disable ieee8021x_blocked while clearing key */
146554c0a3aSHans de Goede 				if (strcmp(param->u.crypt.alg, "none") != 0)
147554c0a3aSHans de Goede 					psta->ieee8021x_blocked = false;
148554c0a3aSHans de Goede 
149554c0a3aSHans de Goede 				if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
150f85ac230STeo Dacquet 				    (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled)) {
151554c0a3aSHans de Goede 					psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
152554c0a3aSHans de Goede 				}
153554c0a3aSHans de Goede 
154f85ac230STeo Dacquet 				if (param->u.crypt.set_tx == 1) { /* pairwise key */
155554c0a3aSHans de Goede 					memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
156554c0a3aSHans de Goede 
157f85ac230STeo Dacquet 					if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
158554c0a3aSHans de Goede 						/* DEBUG_ERR(("\nset key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */
159722a3291SFranziska Naepelt 						memcpy(psta->dot11tkiptxmickey.skey, &param->u.crypt.key[16], 8);
160722a3291SFranziska Naepelt 						memcpy(psta->dot11tkiprxmickey.skey, &param->u.crypt.key[24], 8);
161554c0a3aSHans de Goede 
162554c0a3aSHans de Goede 						padapter->securitypriv.busetkipkey = false;
163554c0a3aSHans de Goede 						/* _set_timer(&padapter->securitypriv.tkip_timer, 50); */
164554c0a3aSHans de Goede 					}
165554c0a3aSHans de Goede 
166554c0a3aSHans de Goede 					rtw_setstakey_cmd(padapter, psta, true, true);
167f85ac230STeo Dacquet 				} else { /* group key */
168f85ac230STeo Dacquet 					if (strcmp(param->u.crypt.alg, "TKIP") == 0 || strcmp(param->u.crypt.alg, "CCMP") == 0) {
169554c0a3aSHans de Goede 						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));
170554c0a3aSHans de Goede 						/* only TKIP group key need to install this */
171f85ac230STeo Dacquet 						if (param->u.crypt.key_len > 16) {
172722a3291SFranziska Naepelt 							memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[16], 8);
173722a3291SFranziska Naepelt 							memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[24], 8);
174554c0a3aSHans de Goede 						}
175554c0a3aSHans de Goede 						padapter->securitypriv.binstallGrpkey = true;
176554c0a3aSHans de Goede 
177554c0a3aSHans de Goede 						padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
178554c0a3aSHans de Goede 
179554c0a3aSHans de Goede 						rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1, true);
180f85ac230STeo Dacquet 					} else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
181554c0a3aSHans de Goede 						/* printk("BIP key_len =%d , index =%d @@@@@@@@@@@@@@@@@@\n", param->u.crypt.key_len, param->u.crypt.idx); */
182554c0a3aSHans de Goede 						/* save the IGTK key, length 16 bytes */
183554c0a3aSHans de Goede 						memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
184554c0a3aSHans de Goede 						/*printk("IGTK key below:\n");
185554c0a3aSHans de Goede 						for (no = 0;no<16;no++)
186554c0a3aSHans de Goede 							printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]);
187554c0a3aSHans de Goede 						printk("\n");*/
188554c0a3aSHans de Goede 						padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
189554c0a3aSHans de Goede 						padapter->securitypriv.binstallBIPkey = true;
190554c0a3aSHans de Goede 					}
191554c0a3aSHans de Goede 				}
192554c0a3aSHans de Goede 			}
193554c0a3aSHans de Goede 
194554c0a3aSHans de Goede 			pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
195cd1f1450SMichael Straube 			if (!pbcmc_sta) {
196554c0a3aSHans de Goede 				/* DEBUG_ERR(("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */
197f85ac230STeo Dacquet 			} else {
198554c0a3aSHans de Goede 				/* Jeff: don't disable ieee8021x_blocked while clearing key */
199554c0a3aSHans de Goede 				if (strcmp(param->u.crypt.alg, "none") != 0)
200554c0a3aSHans de Goede 					pbcmc_sta->ieee8021x_blocked = false;
201554c0a3aSHans de Goede 
202554c0a3aSHans de Goede 				if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
203f85ac230STeo Dacquet 				    (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled)) {
204554c0a3aSHans de Goede 					pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
205554c0a3aSHans de Goede 				}
206554c0a3aSHans de Goede 			}
207f85ac230STeo Dacquet 		} else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
208f85ac230STeo Dacquet 			/* adhoc mode */
209554c0a3aSHans de Goede 		}
210554c0a3aSHans de Goede 	}
211554c0a3aSHans de Goede 
212554c0a3aSHans de Goede exit:
213554c0a3aSHans de Goede 
214428715baSAmitoj Kaur Chawla 	kfree(pwep);
215554c0a3aSHans de Goede 	return ret;
216554c0a3aSHans de Goede }
217554c0a3aSHans de Goede 
rtw_set_wpa_ie(struct adapter * padapter,char * pie,unsigned short ielen)218554c0a3aSHans de Goede static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ielen)
219554c0a3aSHans de Goede {
220288f9acaSNishka Dasgupta 	u8 *buf = NULL;
221554c0a3aSHans de Goede 	int group_cipher = 0, pairwise_cipher = 0;
222554c0a3aSHans de Goede 	int ret = 0;
223554c0a3aSHans de Goede 	u8 null_addr[] = {0, 0, 0, 0, 0, 0};
224554c0a3aSHans de Goede 
225cd1f1450SMichael Straube 	if (ielen > MAX_WPA_IE_LEN || !pie) {
226554c0a3aSHans de Goede 		_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
227cd1f1450SMichael Straube 		if (!pie)
228554c0a3aSHans de Goede 			return ret;
229554c0a3aSHans de Goede 		else
230554c0a3aSHans de Goede 			return -EINVAL;
231554c0a3aSHans de Goede 	}
232554c0a3aSHans de Goede 
233f85ac230STeo Dacquet 	if (ielen) {
234554c0a3aSHans de Goede 		buf = rtw_zmalloc(ielen);
235cd1f1450SMichael Straube 		if (!buf) {
236554c0a3aSHans de Goede 			ret =  -ENOMEM;
237554c0a3aSHans de Goede 			goto exit;
238554c0a3aSHans de Goede 		}
239554c0a3aSHans de Goede 
240554c0a3aSHans de Goede 		memcpy(buf, pie, ielen);
241554c0a3aSHans de Goede 
242554c0a3aSHans de Goede 		if (ielen < RSN_HEADER_LEN) {
243554c0a3aSHans de Goede 			ret  = -1;
244554c0a3aSHans de Goede 			goto exit;
245554c0a3aSHans de Goede 		}
246554c0a3aSHans de Goede 
247f85ac230STeo Dacquet 		if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
248554c0a3aSHans de Goede 			padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
249554c0a3aSHans de Goede 			padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
250554c0a3aSHans de Goede 			memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
251554c0a3aSHans de Goede 		}
252554c0a3aSHans de Goede 
253f85ac230STeo Dacquet 		if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
254554c0a3aSHans de Goede 			padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
255554c0a3aSHans de Goede 			padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
256554c0a3aSHans de Goede 			memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
257554c0a3aSHans de Goede 		}
258554c0a3aSHans de Goede 
259554c0a3aSHans de Goede 		if (group_cipher == 0)
260554c0a3aSHans de Goede 			group_cipher = WPA_CIPHER_NONE;
261554c0a3aSHans de Goede 		if (pairwise_cipher == 0)
262554c0a3aSHans de Goede 			pairwise_cipher = WPA_CIPHER_NONE;
263554c0a3aSHans de Goede 
264f85ac230STeo Dacquet 		switch (group_cipher) {
265554c0a3aSHans de Goede 		case WPA_CIPHER_NONE:
266554c0a3aSHans de Goede 			padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
267554c0a3aSHans de Goede 			padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
268554c0a3aSHans de Goede 			break;
269554c0a3aSHans de Goede 		case WPA_CIPHER_WEP40:
270554c0a3aSHans de Goede 			padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
271554c0a3aSHans de Goede 			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
272554c0a3aSHans de Goede 			break;
273554c0a3aSHans de Goede 		case WPA_CIPHER_TKIP:
274554c0a3aSHans de Goede 			padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
275554c0a3aSHans de Goede 			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
276554c0a3aSHans de Goede 			break;
277554c0a3aSHans de Goede 		case WPA_CIPHER_CCMP:
278554c0a3aSHans de Goede 			padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
279554c0a3aSHans de Goede 			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
280554c0a3aSHans de Goede 			break;
281554c0a3aSHans de Goede 		case WPA_CIPHER_WEP104:
282554c0a3aSHans de Goede 			padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
283554c0a3aSHans de Goede 			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
284554c0a3aSHans de Goede 			break;
285554c0a3aSHans de Goede 		}
286554c0a3aSHans de Goede 
287f85ac230STeo Dacquet 		switch (pairwise_cipher) {
288554c0a3aSHans de Goede 		case WPA_CIPHER_NONE:
289554c0a3aSHans de Goede 			padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
290554c0a3aSHans de Goede 			padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
291554c0a3aSHans de Goede 			break;
292554c0a3aSHans de Goede 		case WPA_CIPHER_WEP40:
293554c0a3aSHans de Goede 			padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
294554c0a3aSHans de Goede 			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
295554c0a3aSHans de Goede 			break;
296554c0a3aSHans de Goede 		case WPA_CIPHER_TKIP:
297554c0a3aSHans de Goede 			padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
298554c0a3aSHans de Goede 			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
299554c0a3aSHans de Goede 			break;
300554c0a3aSHans de Goede 		case WPA_CIPHER_CCMP:
301554c0a3aSHans de Goede 			padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
302554c0a3aSHans de Goede 			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
303554c0a3aSHans de Goede 			break;
304554c0a3aSHans de Goede 		case WPA_CIPHER_WEP104:
305554c0a3aSHans de Goede 			padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
306554c0a3aSHans de Goede 			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
307554c0a3aSHans de Goede 			break;
308554c0a3aSHans de Goede 		}
309554c0a3aSHans de Goede 
310554c0a3aSHans de Goede 		_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
311554c0a3aSHans de Goede 		{/* set wps_ie */
312554c0a3aSHans de Goede 			u16 cnt = 0;
313554c0a3aSHans de Goede 			u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
314554c0a3aSHans de Goede 
315f85ac230STeo Dacquet 			while (cnt < ielen) {
316554c0a3aSHans de Goede 				eid = buf[cnt];
317554c0a3aSHans de Goede 
318b05cc3a9SRoss Schmidt 				if ((eid == WLAN_EID_VENDOR_SPECIFIC) && (!memcmp(&buf[cnt + 2], wps_oui, 4))) {
319554c0a3aSHans de Goede 					padapter->securitypriv.wps_ie_len = ((buf[cnt + 1] + 2) < MAX_WPS_IE_LEN) ? (buf[cnt + 1] + 2) : MAX_WPS_IE_LEN;
320554c0a3aSHans de Goede 
321554c0a3aSHans de Goede 					memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
322554c0a3aSHans de Goede 
323554c0a3aSHans de Goede 					set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
324554c0a3aSHans de Goede 
325554c0a3aSHans de Goede 					cnt += buf[cnt + 1] + 2;
326554c0a3aSHans de Goede 
327554c0a3aSHans de Goede 					break;
328554c0a3aSHans de Goede 				} else {
329554c0a3aSHans de Goede 					cnt += buf[cnt + 1] + 2; /* goto next */
330554c0a3aSHans de Goede 				}
331554c0a3aSHans de Goede 			}
332554c0a3aSHans de Goede 		}
333554c0a3aSHans de Goede 	}
334554c0a3aSHans de Goede 
335554c0a3aSHans de Goede 	/* TKIP and AES disallow multicast packets until installing group key */
336105bc6b9SFabio Aiuto 	if (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_ ||
337105bc6b9SFabio Aiuto 	    padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_ ||
338105bc6b9SFabio Aiuto 	    padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
339554c0a3aSHans de Goede 		/* WPS open need to enable multicast */
340554c0a3aSHans de Goede 		/*  check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true) */
341554c0a3aSHans de Goede 		rtw_hal_set_hwreg(padapter, HW_VAR_OFF_RCR_AM, null_addr);
342554c0a3aSHans de Goede 
343554c0a3aSHans de Goede exit:
344554c0a3aSHans de Goede 
3457ad61a38SAishwarya Pant 	kfree(buf);
346554c0a3aSHans de Goede 
347554c0a3aSHans de Goede 	return ret;
348554c0a3aSHans de Goede }
349554c0a3aSHans de Goede 
wpa_set_param(struct net_device * dev,u8 name,u32 value)350554c0a3aSHans de Goede static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
351554c0a3aSHans de Goede {
352554c0a3aSHans de Goede 	uint ret = 0;
35342a18f09SIvan Safonov 	struct adapter *padapter = rtw_netdev_priv(dev);
354554c0a3aSHans de Goede 
355554c0a3aSHans de Goede 	switch (name) {
356554c0a3aSHans de Goede 	case IEEE_PARAM_WPA_ENABLED:
357554c0a3aSHans de Goede 
358554c0a3aSHans de Goede 		padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */
359554c0a3aSHans de Goede 
360554c0a3aSHans de Goede 		/* ret = ieee80211_wpa_enable(ieee, value); */
361554c0a3aSHans de Goede 
362f85ac230STeo Dacquet 		switch ((value) & 0xff) {
363554c0a3aSHans de Goede 		case 1: /* WPA */
364554c0a3aSHans de Goede 			padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
365554c0a3aSHans de Goede 			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
366554c0a3aSHans de Goede 			break;
367554c0a3aSHans de Goede 		case 2: /* WPA2 */
368554c0a3aSHans de Goede 			padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
369554c0a3aSHans de Goede 			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
370554c0a3aSHans de Goede 			break;
371554c0a3aSHans de Goede 		}
372554c0a3aSHans de Goede 
373554c0a3aSHans de Goede 		break;
374554c0a3aSHans de Goede 
375554c0a3aSHans de Goede 	case IEEE_PARAM_TKIP_COUNTERMEASURES:
376554c0a3aSHans de Goede 		/* ieee->tkip_countermeasures =value; */
377554c0a3aSHans de Goede 		break;
378554c0a3aSHans de Goede 
379554c0a3aSHans de Goede 	case IEEE_PARAM_DROP_UNENCRYPTED:
380554c0a3aSHans de Goede 	{
381554c0a3aSHans de Goede 		/* HACK:
382554c0a3aSHans de Goede 		 *
383554c0a3aSHans de Goede 		 * wpa_supplicant calls set_wpa_enabled when the driver
384554c0a3aSHans de Goede 		 * is loaded and unloaded, regardless of if WPA is being
385554c0a3aSHans de Goede 		 * used.  No other calls are made which can be used to
386554c0a3aSHans de Goede 		 * determine if encryption will be used or not prior to
387554c0a3aSHans de Goede 		 * association being expected.  If encryption is not being
388554c0a3aSHans de Goede 		 * used, drop_unencrypted is set to false, else true -- we
389554c0a3aSHans de Goede 		 * can use this to determine if the CAP_PRIVACY_ON bit should
390554c0a3aSHans de Goede 		 * be set.
391554c0a3aSHans de Goede 		 */
392554c0a3aSHans de Goede 		break;
393554c0a3aSHans de Goede 	}
394554c0a3aSHans de Goede 	case IEEE_PARAM_PRIVACY_INVOKED:
395554c0a3aSHans de Goede 
396554c0a3aSHans de Goede 		/* ieee->privacy_invoked =value; */
397554c0a3aSHans de Goede 
398554c0a3aSHans de Goede 		break;
399554c0a3aSHans de Goede 
400554c0a3aSHans de Goede 	case IEEE_PARAM_AUTH_ALGS:
401554c0a3aSHans de Goede 
402554c0a3aSHans de Goede 		ret = wpa_set_auth_algs(dev, value);
403554c0a3aSHans de Goede 
404554c0a3aSHans de Goede 		break;
405554c0a3aSHans de Goede 
406554c0a3aSHans de Goede 	case IEEE_PARAM_IEEE_802_1X:
407554c0a3aSHans de Goede 
408554c0a3aSHans de Goede 		/* ieee->ieee802_1x =value; */
409554c0a3aSHans de Goede 
410554c0a3aSHans de Goede 		break;
411554c0a3aSHans de Goede 
412554c0a3aSHans de Goede 	case IEEE_PARAM_WPAX_SELECT:
413554c0a3aSHans de Goede 
414554c0a3aSHans de Goede 		/*  added for WPA2 mixed mode */
415554c0a3aSHans de Goede 		/*
416554c0a3aSHans de Goede 		spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags);
417554c0a3aSHans de Goede 		ieee->wpax_type_set = 1;
418554c0a3aSHans de Goede 		ieee->wpax_type_notify = value;
419554c0a3aSHans de Goede 		spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags);
420554c0a3aSHans de Goede 		*/
421554c0a3aSHans de Goede 
422554c0a3aSHans de Goede 		break;
423554c0a3aSHans de Goede 
424554c0a3aSHans de Goede 	default:
425554c0a3aSHans de Goede 
426554c0a3aSHans de Goede 		ret = -EOPNOTSUPP;
427554c0a3aSHans de Goede 
428554c0a3aSHans de Goede 		break;
429554c0a3aSHans de Goede 	}
430554c0a3aSHans de Goede 
431554c0a3aSHans de Goede 	return ret;
432554c0a3aSHans de Goede }
433554c0a3aSHans de Goede 
wpa_mlme(struct net_device * dev,u32 command,u32 reason)434554c0a3aSHans de Goede static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
435554c0a3aSHans de Goede {
436554c0a3aSHans de Goede 	int ret = 0;
43742a18f09SIvan Safonov 	struct adapter *padapter = rtw_netdev_priv(dev);
438554c0a3aSHans de Goede 
439f85ac230STeo Dacquet 	switch (command) {
440554c0a3aSHans de Goede 	case IEEE_MLME_STA_DEAUTH:
441554c0a3aSHans de Goede 
442554c0a3aSHans de Goede 		if (!rtw_set_802_11_disassociate(padapter))
443554c0a3aSHans de Goede 			ret = -1;
444554c0a3aSHans de Goede 
445554c0a3aSHans de Goede 		break;
446554c0a3aSHans de Goede 
447554c0a3aSHans de Goede 	case IEEE_MLME_STA_DISASSOC:
448554c0a3aSHans de Goede 
449554c0a3aSHans de Goede 		if (!rtw_set_802_11_disassociate(padapter))
450554c0a3aSHans de Goede 			ret = -1;
451554c0a3aSHans de Goede 
452554c0a3aSHans de Goede 		break;
453554c0a3aSHans de Goede 
454554c0a3aSHans de Goede 	default:
455554c0a3aSHans de Goede 		ret = -EOPNOTSUPP;
456554c0a3aSHans de Goede 		break;
457554c0a3aSHans de Goede 	}
458554c0a3aSHans de Goede 
459554c0a3aSHans de Goede 	return ret;
460554c0a3aSHans de Goede }
461554c0a3aSHans de Goede 
wpa_supplicant_ioctl(struct net_device * dev,struct iw_point * p)462554c0a3aSHans de Goede static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
463554c0a3aSHans de Goede {
464554c0a3aSHans de Goede 	struct ieee_param *param;
465554c0a3aSHans de Goede 	uint ret = 0;
466554c0a3aSHans de Goede 
467554c0a3aSHans de Goede 	/* down(&ieee->wx_sem); */
468554c0a3aSHans de Goede 
4699a4556bdSLarry Finger 	if (!p->pointer || p->length != sizeof(struct ieee_param))
4709a4556bdSLarry Finger 		return -EINVAL;
471554c0a3aSHans de Goede 
4722ef2b7c2SJoe Perches 	param = rtw_malloc(p->length);
473cd1f1450SMichael Straube 	if (!param)
4749a4556bdSLarry Finger 		return -ENOMEM;
475554c0a3aSHans de Goede 
476f85ac230STeo Dacquet 	if (copy_from_user(param, p->pointer, p->length)) {
477428715baSAmitoj Kaur Chawla 		kfree(param);
4789a4556bdSLarry Finger 		return -EFAULT;
479554c0a3aSHans de Goede 	}
480554c0a3aSHans de Goede 
481554c0a3aSHans de Goede 	switch (param->cmd) {
482554c0a3aSHans de Goede 	case IEEE_CMD_SET_WPA_PARAM:
483554c0a3aSHans de Goede 		ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
484554c0a3aSHans de Goede 		break;
485554c0a3aSHans de Goede 
486554c0a3aSHans de Goede 	case IEEE_CMD_SET_WPA_IE:
487554c0a3aSHans de Goede 		/* ret = wpa_set_wpa_ie(dev, param, p->length); */
48842a18f09SIvan Safonov 		ret =  rtw_set_wpa_ie(rtw_netdev_priv(dev), (char *)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
489554c0a3aSHans de Goede 		break;
490554c0a3aSHans de Goede 
491554c0a3aSHans de Goede 	case IEEE_CMD_SET_ENCRYPTION:
492554c0a3aSHans de Goede 		ret = wpa_set_encryption(dev, param, p->length);
493554c0a3aSHans de Goede 		break;
494554c0a3aSHans de Goede 
495554c0a3aSHans de Goede 	case IEEE_CMD_MLME:
496554c0a3aSHans de Goede 		ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
497554c0a3aSHans de Goede 		break;
498554c0a3aSHans de Goede 
499554c0a3aSHans de Goede 	default:
500554c0a3aSHans de Goede 		ret = -EOPNOTSUPP;
501554c0a3aSHans de Goede 		break;
502554c0a3aSHans de Goede 	}
503554c0a3aSHans de Goede 
504554c0a3aSHans de Goede 	if (ret == 0 && copy_to_user(p->pointer, param, p->length))
505554c0a3aSHans de Goede 		ret = -EFAULT;
506554c0a3aSHans de Goede 
507428715baSAmitoj Kaur Chawla 	kfree(param);
508554c0a3aSHans de Goede 
509554c0a3aSHans de Goede 	/* up(&ieee->wx_sem); */
510554c0a3aSHans de Goede 	return ret;
511554c0a3aSHans de Goede }
512554c0a3aSHans de Goede 
rtw_set_encryption(struct net_device * dev,struct ieee_param * param,u32 param_len)513554c0a3aSHans de Goede static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
514554c0a3aSHans de Goede {
515554c0a3aSHans de Goede 	int ret = 0;
516554c0a3aSHans de Goede 	u32 wep_key_idx, wep_key_len, wep_total_len;
517554c0a3aSHans de Goede 	struct ndis_802_11_wep	 *pwep = NULL;
518554c0a3aSHans de Goede 	struct sta_info *psta = NULL, *pbcmc_sta = NULL;
51942a18f09SIvan Safonov 	struct adapter *padapter = rtw_netdev_priv(dev);
520554c0a3aSHans de Goede 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
521722a3291SFranziska Naepelt 	struct security_priv *psecuritypriv = &padapter->securitypriv;
522554c0a3aSHans de Goede 	struct sta_priv *pstapriv = &padapter->stapriv;
52314b6cff5SArnd Bergmann 	char *txkey = padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey;
52414b6cff5SArnd Bergmann 	char *rxkey = padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey;
52514b6cff5SArnd Bergmann 	char *grpkey = psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey;
526554c0a3aSHans de Goede 
527554c0a3aSHans de Goede 	param->u.crypt.err = 0;
528554c0a3aSHans de Goede 	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
529554c0a3aSHans de Goede 
530554c0a3aSHans de Goede 	/* sizeof(struct ieee_param) = 64 bytes; */
531554c0a3aSHans de Goede 	/* if (param_len !=  (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) */
532f85ac230STeo Dacquet 	if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {
533554c0a3aSHans de Goede 		ret =  -EINVAL;
534554c0a3aSHans de Goede 		goto exit;
535554c0a3aSHans de Goede 	}
536554c0a3aSHans de Goede 
537554c0a3aSHans de Goede 	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
538554c0a3aSHans de Goede 	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
539f85ac230STeo Dacquet 	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
540f85ac230STeo Dacquet 		if (param->u.crypt.idx >= WEP_KEYS) {
541554c0a3aSHans de Goede 			ret = -EINVAL;
542554c0a3aSHans de Goede 			goto exit;
543554c0a3aSHans de Goede 		}
544f85ac230STeo Dacquet 	} else {
545554c0a3aSHans de Goede 		psta = rtw_get_stainfo(pstapriv, param->sta_addr);
546709c8e49SFabio Aiuto 		if (!psta)
547554c0a3aSHans de Goede 			/* ret = -EINVAL; */
548554c0a3aSHans de Goede 			goto exit;
549554c0a3aSHans de Goede 	}
550554c0a3aSHans de Goede 
551cd1f1450SMichael Straube 	if (strcmp(param->u.crypt.alg, "none") == 0 && !psta) {
552554c0a3aSHans de Goede 		/* todo:clear default encryption keys */
553554c0a3aSHans de Goede 
554554c0a3aSHans de Goede 		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
555554c0a3aSHans de Goede 		psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
556554c0a3aSHans de Goede 		psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
557554c0a3aSHans de Goede 		psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
558554c0a3aSHans de Goede 
559554c0a3aSHans de Goede 		goto exit;
560554c0a3aSHans de Goede 	}
561554c0a3aSHans de Goede 
562cd1f1450SMichael Straube 	if (strcmp(param->u.crypt.alg, "WEP") == 0 && !psta) {
563554c0a3aSHans de Goede 		wep_key_idx = param->u.crypt.idx;
564554c0a3aSHans de Goede 		wep_key_len = param->u.crypt.key_len;
565554c0a3aSHans de Goede 
566f85ac230STeo Dacquet 		if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
567554c0a3aSHans de Goede 			ret = -EINVAL;
568554c0a3aSHans de Goede 			goto exit;
569554c0a3aSHans de Goede 		}
570554c0a3aSHans de Goede 
571f85ac230STeo Dacquet 		if (wep_key_len > 0) {
572554c0a3aSHans de Goede 			wep_key_len = wep_key_len <= 5 ? 5 : 13;
573f133717eSFabio Aiuto 			wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, key_material);
57467ea0a2aSKees Cook 			/* Allocate a full structure to avoid potentially running off the end. */
57567ea0a2aSKees Cook 			pwep = kzalloc(sizeof(*pwep), GFP_KERNEL);
576e427bdd8SFabio Aiuto 			if (!pwep)
577554c0a3aSHans de Goede 				goto exit;
578554c0a3aSHans de Goede 
579f133717eSFabio Aiuto 			pwep->key_length = wep_key_len;
580f133717eSFabio Aiuto 			pwep->length = wep_total_len;
581554c0a3aSHans de Goede 		}
582554c0a3aSHans de Goede 
583f133717eSFabio Aiuto 		pwep->key_index = wep_key_idx;
584554c0a3aSHans de Goede 
585f133717eSFabio Aiuto 		memcpy(pwep->key_material,  param->u.crypt.key, pwep->key_length);
586554c0a3aSHans de Goede 
587f85ac230STeo Dacquet 		if (param->u.crypt.set_tx) {
588554c0a3aSHans de Goede 			psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
589554c0a3aSHans de Goede 			psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
590554c0a3aSHans de Goede 			psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
591554c0a3aSHans de Goede 			psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
592554c0a3aSHans de Goede 
593f133717eSFabio Aiuto 			if (pwep->key_length == 13) {
594554c0a3aSHans de Goede 				psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
595554c0a3aSHans de Goede 				psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
596554c0a3aSHans de Goede 			}
597554c0a3aSHans de Goede 
598554c0a3aSHans de Goede 			psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
599554c0a3aSHans de Goede 
600722a3291SFranziska Naepelt 			memcpy(&psecuritypriv->dot11DefKey[wep_key_idx].skey[0], pwep->key_material, pwep->key_length);
601554c0a3aSHans de Goede 
602f133717eSFabio Aiuto 			psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->key_length;
603554c0a3aSHans de Goede 
604f133717eSFabio Aiuto 			rtw_ap_set_wep_key(padapter, pwep->key_material, pwep->key_length, wep_key_idx, 1);
605f85ac230STeo Dacquet 		} else {
606554c0a3aSHans de Goede 			/* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
607554c0a3aSHans de Goede 			/* psecuritypriv->dot11PrivacyKeyIndex =keyid", but can rtw_set_key to cam */
608554c0a3aSHans de Goede 
609722a3291SFranziska Naepelt 			memcpy(&psecuritypriv->dot11DefKey[wep_key_idx].skey[0], pwep->key_material, pwep->key_length);
610554c0a3aSHans de Goede 
611f133717eSFabio Aiuto 			psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->key_length;
612554c0a3aSHans de Goede 
613f133717eSFabio Aiuto 			rtw_ap_set_wep_key(padapter, pwep->key_material, pwep->key_length, wep_key_idx, 0);
614554c0a3aSHans de Goede 		}
615554c0a3aSHans de Goede 
616554c0a3aSHans de Goede 		goto exit;
617554c0a3aSHans de Goede 	}
618554c0a3aSHans de Goede 
619f85ac230STeo Dacquet 	if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /*  group key */
620f85ac230STeo Dacquet 		if (param->u.crypt.set_tx == 1) {
621f85ac230STeo Dacquet 			if (strcmp(param->u.crypt.alg, "WEP") == 0) {
62214b6cff5SArnd Bergmann 				memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
623554c0a3aSHans de Goede 
624554c0a3aSHans de Goede 				psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
625554c0a3aSHans de Goede 				if (param->u.crypt.key_len == 13)
626554c0a3aSHans de Goede 					psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
627554c0a3aSHans de Goede 
628f85ac230STeo Dacquet 			} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
629554c0a3aSHans de Goede 				psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
630554c0a3aSHans de Goede 
63114b6cff5SArnd Bergmann 				memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
632554c0a3aSHans de Goede 
633554c0a3aSHans de Goede 				/* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
634554c0a3aSHans de Goede 				/* set mic key */
635722a3291SFranziska Naepelt 				memcpy(txkey, &param->u.crypt.key[16], 8);
636722a3291SFranziska Naepelt 				memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[24], 8);
637554c0a3aSHans de Goede 
638554c0a3aSHans de Goede 				psecuritypriv->busetkipkey = true;
639554c0a3aSHans de Goede 
6404762c171SFranziska Naepelt 			} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
641554c0a3aSHans de Goede 				psecuritypriv->dot118021XGrpPrivacy = _AES_;
642554c0a3aSHans de Goede 
64314b6cff5SArnd Bergmann 				memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
644f85ac230STeo Dacquet 			} else {
645554c0a3aSHans de Goede 				psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
646554c0a3aSHans de Goede 			}
647554c0a3aSHans de Goede 
648554c0a3aSHans de Goede 			psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
649554c0a3aSHans de Goede 
650554c0a3aSHans de Goede 			psecuritypriv->binstallGrpkey = true;
651554c0a3aSHans de Goede 
652554c0a3aSHans de Goede 			psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
653554c0a3aSHans de Goede 
654554c0a3aSHans de Goede 			rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
655554c0a3aSHans de Goede 
656554c0a3aSHans de Goede 			pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
657f85ac230STeo Dacquet 			if (pbcmc_sta) {
658554c0a3aSHans de Goede 				pbcmc_sta->ieee8021x_blocked = false;
659554c0a3aSHans de Goede 				pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
660554c0a3aSHans de Goede 			}
661554c0a3aSHans de Goede 		}
662554c0a3aSHans de Goede 
663554c0a3aSHans de Goede 		goto exit;
664554c0a3aSHans de Goede 	}
665554c0a3aSHans de Goede 
666f85ac230STeo Dacquet 	if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /*  psk/802_1x */
667f85ac230STeo Dacquet 		if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
668f85ac230STeo Dacquet 			if (param->u.crypt.set_tx == 1)	{
669554c0a3aSHans de Goede 				memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
670554c0a3aSHans de Goede 
671f85ac230STeo Dacquet 				if (strcmp(param->u.crypt.alg, "WEP") == 0) {
672554c0a3aSHans de Goede 					psta->dot118021XPrivacy = _WEP40_;
673554c0a3aSHans de Goede 					if (param->u.crypt.key_len == 13)
674554c0a3aSHans de Goede 						psta->dot118021XPrivacy = _WEP104_;
675f85ac230STeo Dacquet 				} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
676554c0a3aSHans de Goede 					psta->dot118021XPrivacy = _TKIP_;
677554c0a3aSHans de Goede 
678554c0a3aSHans de Goede 					/* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
679554c0a3aSHans de Goede 					/* set mic key */
680722a3291SFranziska Naepelt 					memcpy(psta->dot11tkiptxmickey.skey, &param->u.crypt.key[16], 8);
681722a3291SFranziska Naepelt 					memcpy(psta->dot11tkiprxmickey.skey, &param->u.crypt.key[24], 8);
682554c0a3aSHans de Goede 
683554c0a3aSHans de Goede 					psecuritypriv->busetkipkey = true;
684554c0a3aSHans de Goede 
685f85ac230STeo Dacquet 				} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
686554c0a3aSHans de Goede 					psta->dot118021XPrivacy = _AES_;
687f85ac230STeo Dacquet 				} else {
688554c0a3aSHans de Goede 					psta->dot118021XPrivacy = _NO_PRIVACY_;
689554c0a3aSHans de Goede 				}
690554c0a3aSHans de Goede 
691554c0a3aSHans de Goede 				rtw_ap_set_pairwise_key(padapter, psta);
692554c0a3aSHans de Goede 
693554c0a3aSHans de Goede 				psta->ieee8021x_blocked = false;
694554c0a3aSHans de Goede 
695f85ac230STeo Dacquet 			} else { /* group key??? */
696f85ac230STeo Dacquet 				if (strcmp(param->u.crypt.alg, "WEP") == 0) {
69714b6cff5SArnd Bergmann 					memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
698554c0a3aSHans de Goede 
699554c0a3aSHans de Goede 					psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
700554c0a3aSHans de Goede 					if (param->u.crypt.key_len == 13)
701554c0a3aSHans de Goede 						psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
702f85ac230STeo Dacquet 				} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
703554c0a3aSHans de Goede 					psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
704554c0a3aSHans de Goede 
70514b6cff5SArnd Bergmann 					memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
706554c0a3aSHans de Goede 
707554c0a3aSHans de Goede 					/* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
708554c0a3aSHans de Goede 					/* set mic key */
709722a3291SFranziska Naepelt 					memcpy(txkey, &param->u.crypt.key[16], 8);
710722a3291SFranziska Naepelt 					memcpy(rxkey, &param->u.crypt.key[24], 8);
711554c0a3aSHans de Goede 
712554c0a3aSHans de Goede 					psecuritypriv->busetkipkey = true;
713554c0a3aSHans de Goede 
714f85ac230STeo Dacquet 				} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
715554c0a3aSHans de Goede 					psecuritypriv->dot118021XGrpPrivacy = _AES_;
716554c0a3aSHans de Goede 
71714b6cff5SArnd Bergmann 					memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
718f85ac230STeo Dacquet 				} else {
719554c0a3aSHans de Goede 					psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
720554c0a3aSHans de Goede 				}
721554c0a3aSHans de Goede 
722554c0a3aSHans de Goede 				psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
723554c0a3aSHans de Goede 
724554c0a3aSHans de Goede 				psecuritypriv->binstallGrpkey = true;
725554c0a3aSHans de Goede 
726554c0a3aSHans de Goede 				psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
727554c0a3aSHans de Goede 
728554c0a3aSHans de Goede 				rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
729554c0a3aSHans de Goede 
730554c0a3aSHans de Goede 				pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
731f85ac230STeo Dacquet 				if (pbcmc_sta) {
732554c0a3aSHans de Goede 					pbcmc_sta->ieee8021x_blocked = false;
733554c0a3aSHans de Goede 					pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
734554c0a3aSHans de Goede 				}
735554c0a3aSHans de Goede 			}
736554c0a3aSHans de Goede 		}
737554c0a3aSHans de Goede 	}
738554c0a3aSHans de Goede 
739554c0a3aSHans de Goede exit:
740428715baSAmitoj Kaur Chawla 	kfree(pwep);
741554c0a3aSHans de Goede 
742554c0a3aSHans de Goede 	return ret;
743554c0a3aSHans de Goede }
744554c0a3aSHans de Goede 
rtw_set_beacon(struct net_device * dev,struct ieee_param * param,int len)745554c0a3aSHans de Goede static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
746554c0a3aSHans de Goede {
747554c0a3aSHans de Goede 	int ret = 0;
74842a18f09SIvan Safonov 	struct adapter *padapter = rtw_netdev_priv(dev);
749722a3291SFranziska Naepelt 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
750554c0a3aSHans de Goede 	struct sta_priv *pstapriv = &padapter->stapriv;
751554c0a3aSHans de Goede 	unsigned char *pbuf = param->u.bcn_ie.buf;
752554c0a3aSHans de Goede 
753554c0a3aSHans de Goede 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
754554c0a3aSHans de Goede 		return -EINVAL;
755554c0a3aSHans de Goede 
756554c0a3aSHans de Goede 	memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
757554c0a3aSHans de Goede 
758554c0a3aSHans de Goede 	if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
759554c0a3aSHans de Goede 		pstapriv->max_num_sta = NUM_STA;
760554c0a3aSHans de Goede 
761554c0a3aSHans de Goede 	if (rtw_check_beacon_data(padapter, pbuf,  (len - 12 - 2)) == _SUCCESS)/*  12 = param header, 2:no packed */
762554c0a3aSHans de Goede 		ret = 0;
763554c0a3aSHans de Goede 	else
764554c0a3aSHans de Goede 		ret = -EINVAL;
765554c0a3aSHans de Goede 
766554c0a3aSHans de Goede 	return ret;
767554c0a3aSHans de Goede }
768554c0a3aSHans de Goede 
rtw_hostapd_sta_flush(struct net_device * dev)769371ec021SHariprasad Kelam static void rtw_hostapd_sta_flush(struct net_device *dev)
770554c0a3aSHans de Goede {
771554c0a3aSHans de Goede 	/* _irqL irqL; */
772554c0a3aSHans de Goede 	/* struct list_head	*phead, *plist; */
773554c0a3aSHans de Goede 	/* struct sta_info *psta = NULL; */
77442a18f09SIvan Safonov 	struct adapter *padapter = rtw_netdev_priv(dev);
775554c0a3aSHans de Goede 	/* struct sta_priv *pstapriv = &padapter->stapriv; */
776554c0a3aSHans de Goede 
777554c0a3aSHans de Goede 	flush_all_cam_entry(padapter);	/* clear CAM */
778554c0a3aSHans de Goede 
779371ec021SHariprasad Kelam 	rtw_sta_flush(padapter);
780554c0a3aSHans de Goede }
781554c0a3aSHans de Goede 
rtw_add_sta(struct net_device * dev,struct ieee_param * param)782554c0a3aSHans de Goede static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
783554c0a3aSHans de Goede {
784554c0a3aSHans de Goede 	int ret = 0;
785554c0a3aSHans de Goede 	struct sta_info *psta = NULL;
78642a18f09SIvan Safonov 	struct adapter *padapter = rtw_netdev_priv(dev);
787722a3291SFranziska Naepelt 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
788554c0a3aSHans de Goede 	struct sta_priv *pstapriv = &padapter->stapriv;
789554c0a3aSHans de Goede 
790554c0a3aSHans de Goede 	if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true)
791554c0a3aSHans de Goede 		return -EINVAL;
792554c0a3aSHans de Goede 
793554c0a3aSHans de Goede 	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
794554c0a3aSHans de Goede 	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
795f85ac230STeo Dacquet 	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
796554c0a3aSHans de Goede 		return -EINVAL;
797554c0a3aSHans de Goede 	}
798554c0a3aSHans de Goede 
799554c0a3aSHans de Goede /*
800554c0a3aSHans de Goede 	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
801554c0a3aSHans de Goede 	if (psta)
802554c0a3aSHans de Goede 	{
803554c0a3aSHans de Goede 		rtw_free_stainfo(padapter,  psta);
804554c0a3aSHans de Goede 
805554c0a3aSHans de Goede 		psta = NULL;
806554c0a3aSHans de Goede 	}
807554c0a3aSHans de Goede */
808554c0a3aSHans de Goede 	/* psta = rtw_alloc_stainfo(pstapriv, param->sta_addr); */
809554c0a3aSHans de Goede 	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
810f85ac230STeo Dacquet 	if (psta) {
811554c0a3aSHans de Goede 		int flags = param->u.add_sta.flags;
812554c0a3aSHans de Goede 
813554c0a3aSHans de Goede 		psta->aid = param->u.add_sta.aid;/* aid = 1~2007 */
814554c0a3aSHans de Goede 
815554c0a3aSHans de Goede 		memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
816554c0a3aSHans de Goede 
817554c0a3aSHans de Goede 		/* check wmm cap. */
818554c0a3aSHans de Goede 		if (WLAN_STA_WME & flags)
819554c0a3aSHans de Goede 			psta->qos_option = 1;
820554c0a3aSHans de Goede 		else
821554c0a3aSHans de Goede 			psta->qos_option = 0;
822554c0a3aSHans de Goede 
823554c0a3aSHans de Goede 		if (pmlmepriv->qospriv.qos_option == 0)
824554c0a3aSHans de Goede 			psta->qos_option = 0;
825554c0a3aSHans de Goede 
826554c0a3aSHans de Goede 		/* chec 802.11n ht cap. */
827f85ac230STeo Dacquet 		if (WLAN_STA_HT & flags) {
828554c0a3aSHans de Goede 			psta->htpriv.ht_option = true;
829554c0a3aSHans de Goede 			psta->qos_option = 1;
830c25d8a7dSRoss Schmidt 			memcpy((void *)&psta->htpriv.ht_cap, (void *)&param->u.add_sta.ht_cap, sizeof(struct ieee80211_ht_cap));
831f85ac230STeo Dacquet 		} else {
832554c0a3aSHans de Goede 			psta->htpriv.ht_option = false;
833554c0a3aSHans de Goede 		}
834554c0a3aSHans de Goede 
835*e1bfd974SFranziska Naepelt 		if (!pmlmepriv->htpriv.ht_option)
836554c0a3aSHans de Goede 			psta->htpriv.ht_option = false;
837554c0a3aSHans de Goede 
838554c0a3aSHans de Goede 		update_sta_info_apmode(padapter, psta);
839554c0a3aSHans de Goede 
840f85ac230STeo Dacquet 	} else {
841554c0a3aSHans de Goede 		ret = -ENOMEM;
842554c0a3aSHans de Goede 	}
843554c0a3aSHans de Goede 
844554c0a3aSHans de Goede 	return ret;
845554c0a3aSHans de Goede }
846554c0a3aSHans de Goede 
rtw_del_sta(struct net_device * dev,struct ieee_param * param)847554c0a3aSHans de Goede static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
848554c0a3aSHans de Goede {
849554c0a3aSHans de Goede 	int ret = 0;
850554c0a3aSHans de Goede 	struct sta_info *psta = NULL;
85142a18f09SIvan Safonov 	struct adapter *padapter = rtw_netdev_priv(dev);
852722a3291SFranziska Naepelt 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
853554c0a3aSHans de Goede 	struct sta_priv *pstapriv = &padapter->stapriv;
854554c0a3aSHans de Goede 
855554c0a3aSHans de Goede 	if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true)
856554c0a3aSHans de Goede 		return -EINVAL;
857554c0a3aSHans de Goede 
858554c0a3aSHans de Goede 	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
859554c0a3aSHans de Goede 	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
860f85ac230STeo Dacquet 	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
861554c0a3aSHans de Goede 		return -EINVAL;
862554c0a3aSHans de Goede 	}
863554c0a3aSHans de Goede 
864554c0a3aSHans de Goede 	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
865f85ac230STeo Dacquet 	if (psta) {
866554c0a3aSHans de Goede 		u8 updated = false;
867554c0a3aSHans de Goede 
868554c0a3aSHans de Goede 		spin_lock_bh(&pstapriv->asoc_list_lock);
869f85ac230STeo Dacquet 		if (list_empty(&psta->asoc_list) == false) {
870554c0a3aSHans de Goede 			list_del_init(&psta->asoc_list);
871554c0a3aSHans de Goede 			pstapriv->asoc_list_cnt--;
872554c0a3aSHans de Goede 			updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
873554c0a3aSHans de Goede 		}
874554c0a3aSHans de Goede 		spin_unlock_bh(&pstapriv->asoc_list_lock);
875554c0a3aSHans de Goede 
876554c0a3aSHans de Goede 		associated_clients_update(padapter, updated);
877554c0a3aSHans de Goede 
878554c0a3aSHans de Goede 		psta = NULL;
879554c0a3aSHans de Goede 	}
880554c0a3aSHans de Goede 
881554c0a3aSHans de Goede 	return ret;
882554c0a3aSHans de Goede }
883554c0a3aSHans de Goede 
rtw_ioctl_get_sta_data(struct net_device * dev,struct ieee_param * param,int len)884554c0a3aSHans de Goede static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
885554c0a3aSHans de Goede {
886554c0a3aSHans de Goede 	int ret = 0;
887554c0a3aSHans de Goede 	struct sta_info *psta = NULL;
88842a18f09SIvan Safonov 	struct adapter *padapter = rtw_netdev_priv(dev);
889722a3291SFranziska Naepelt 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
890554c0a3aSHans de Goede 	struct sta_priv *pstapriv = &padapter->stapriv;
891554c0a3aSHans de Goede 	struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
892554c0a3aSHans de Goede 	struct sta_data *psta_data = (struct sta_data *)param_ex->data;
893554c0a3aSHans de Goede 
894554c0a3aSHans de Goede 	if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true)
895554c0a3aSHans de Goede 		return -EINVAL;
896554c0a3aSHans de Goede 
897554c0a3aSHans de Goede 	if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
898554c0a3aSHans de Goede 	    param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
899f85ac230STeo Dacquet 	    param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff) {
900554c0a3aSHans de Goede 		return -EINVAL;
901554c0a3aSHans de Goede 	}
902554c0a3aSHans de Goede 
903554c0a3aSHans de Goede 	psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
904f85ac230STeo Dacquet 	if (psta) {
905554c0a3aSHans de Goede 		psta_data->aid = (u16)psta->aid;
906554c0a3aSHans de Goede 		psta_data->capability = psta->capability;
907554c0a3aSHans de Goede 		psta_data->flags = psta->flags;
908554c0a3aSHans de Goede 
909554c0a3aSHans de Goede /*
910554c0a3aSHans de Goede 		nonerp_set : BIT(0)
911554c0a3aSHans de Goede 		no_short_slot_time_set : BIT(1)
912554c0a3aSHans de Goede 		no_short_preamble_set : BIT(2)
913554c0a3aSHans de Goede 		no_ht_gf_set : BIT(3)
914554c0a3aSHans de Goede 		no_ht_set : BIT(4)
915554c0a3aSHans de Goede 		ht_20mhz_set : BIT(5)
916554c0a3aSHans de Goede */
917554c0a3aSHans de Goede 
918554c0a3aSHans de Goede 		psta_data->sta_set = ((psta->nonerp_set) |
919554c0a3aSHans de Goede 							 (psta->no_short_slot_time_set << 1) |
920554c0a3aSHans de Goede 							 (psta->no_short_preamble_set << 2) |
921554c0a3aSHans de Goede 							 (psta->no_ht_gf_set << 3) |
922554c0a3aSHans de Goede 							 (psta->no_ht_set << 4) |
923554c0a3aSHans de Goede 							 (psta->ht_20mhz_set << 5));
924554c0a3aSHans de Goede 
925554c0a3aSHans de Goede 		psta_data->tx_supp_rates_len =  psta->bssratelen;
926554c0a3aSHans de Goede 		memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
927c25d8a7dSRoss Schmidt 		memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct ieee80211_ht_cap));
928554c0a3aSHans de Goede 		psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
929554c0a3aSHans de Goede 		psta_data->rx_bytes = psta->sta_stats.rx_bytes;
930554c0a3aSHans de Goede 		psta_data->rx_drops = psta->sta_stats.rx_drops;
931554c0a3aSHans de Goede 
932554c0a3aSHans de Goede 		psta_data->tx_pkts = psta->sta_stats.tx_pkts;
933554c0a3aSHans de Goede 		psta_data->tx_bytes = psta->sta_stats.tx_bytes;
934554c0a3aSHans de Goede 		psta_data->tx_drops = psta->sta_stats.tx_drops;
935554c0a3aSHans de Goede 
936f85ac230STeo Dacquet 	} else {
937554c0a3aSHans de Goede 		ret = -1;
938554c0a3aSHans de Goede 	}
939554c0a3aSHans de Goede 
940554c0a3aSHans de Goede 	return ret;
941554c0a3aSHans de Goede }
942554c0a3aSHans de Goede 
rtw_get_sta_wpaie(struct net_device * dev,struct ieee_param * param)943554c0a3aSHans de Goede static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
944554c0a3aSHans de Goede {
945554c0a3aSHans de Goede 	int ret = 0;
946554c0a3aSHans de Goede 	struct sta_info *psta = NULL;
94742a18f09SIvan Safonov 	struct adapter *padapter = rtw_netdev_priv(dev);
948722a3291SFranziska Naepelt 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
949554c0a3aSHans de Goede 	struct sta_priv *pstapriv = &padapter->stapriv;
950554c0a3aSHans de Goede 
951554c0a3aSHans de Goede 	if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true)
952554c0a3aSHans de Goede 		return -EINVAL;
953554c0a3aSHans de Goede 
954554c0a3aSHans de Goede 	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
955554c0a3aSHans de Goede 	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
956f85ac230STeo Dacquet 	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
957554c0a3aSHans de Goede 		return -EINVAL;
958554c0a3aSHans de Goede 	}
959554c0a3aSHans de Goede 
960554c0a3aSHans de Goede 	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
961f85ac230STeo Dacquet 	if (psta) {
962b05cc3a9SRoss Schmidt 		if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC)) {
963554c0a3aSHans de Goede 			int wpa_ie_len;
964554c0a3aSHans de Goede 			int copy_len;
965554c0a3aSHans de Goede 
966554c0a3aSHans de Goede 			wpa_ie_len = psta->wpa_ie[1];
967554c0a3aSHans de Goede 
968554c0a3aSHans de Goede 			copy_len = ((wpa_ie_len + 2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)) : (wpa_ie_len + 2);
969554c0a3aSHans de Goede 
970554c0a3aSHans de Goede 			param->u.wpa_ie.len = copy_len;
971554c0a3aSHans de Goede 
972554c0a3aSHans de Goede 			memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
973554c0a3aSHans de Goede 		}
974f85ac230STeo Dacquet 	} else {
975554c0a3aSHans de Goede 		ret = -1;
976554c0a3aSHans de Goede 	}
977554c0a3aSHans de Goede 
978554c0a3aSHans de Goede 	return ret;
979554c0a3aSHans de Goede }
980554c0a3aSHans de Goede 
rtw_set_wps_beacon(struct net_device * dev,struct ieee_param * param,int len)981554c0a3aSHans de Goede static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
982554c0a3aSHans de Goede {
983554c0a3aSHans de Goede 	int ret = 0;
984554c0a3aSHans de Goede 	unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
98542a18f09SIvan Safonov 	struct adapter *padapter = rtw_netdev_priv(dev);
986722a3291SFranziska Naepelt 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
987722a3291SFranziska Naepelt 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
988554c0a3aSHans de Goede 	int ie_len;
989554c0a3aSHans de Goede 
990554c0a3aSHans de Goede 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
991554c0a3aSHans de Goede 		return -EINVAL;
992554c0a3aSHans de Goede 
993554c0a3aSHans de Goede 	ie_len = len - 12 - 2;/*  12 = param header, 2:no packed */
994554c0a3aSHans de Goede 
995554c0a3aSHans de Goede 	kfree(pmlmepriv->wps_beacon_ie);
996554c0a3aSHans de Goede 	pmlmepriv->wps_beacon_ie = NULL;
997554c0a3aSHans de Goede 
998f85ac230STeo Dacquet 	if (ie_len > 0) {
999554c0a3aSHans de Goede 		pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
1000554c0a3aSHans de Goede 		pmlmepriv->wps_beacon_ie_len = ie_len;
1001e427bdd8SFabio Aiuto 		if (!pmlmepriv->wps_beacon_ie)
1002554c0a3aSHans de Goede 			return -EINVAL;
1003554c0a3aSHans de Goede 
1004554c0a3aSHans de Goede 		memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
1005554c0a3aSHans de Goede 
1006b05cc3a9SRoss Schmidt 		update_beacon(padapter, WLAN_EID_VENDOR_SPECIFIC, wps_oui, true);
1007554c0a3aSHans de Goede 
1008554c0a3aSHans de Goede 		pmlmeext->bstart_bss = true;
1009554c0a3aSHans de Goede 	}
1010554c0a3aSHans de Goede 
1011554c0a3aSHans de Goede 	return ret;
1012554c0a3aSHans de Goede }
1013554c0a3aSHans de Goede 
rtw_set_wps_probe_resp(struct net_device * dev,struct ieee_param * param,int len)1014554c0a3aSHans de Goede static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
1015554c0a3aSHans de Goede {
1016554c0a3aSHans de Goede 	int ret = 0;
101742a18f09SIvan Safonov 	struct adapter *padapter = rtw_netdev_priv(dev);
1018722a3291SFranziska Naepelt 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1019554c0a3aSHans de Goede 	int ie_len;
1020554c0a3aSHans de Goede 
1021554c0a3aSHans de Goede 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
1022554c0a3aSHans de Goede 		return -EINVAL;
1023554c0a3aSHans de Goede 
1024554c0a3aSHans de Goede 	ie_len = len - 12 - 2;/*  12 = param header, 2:no packed */
1025554c0a3aSHans de Goede 
1026554c0a3aSHans de Goede 	kfree(pmlmepriv->wps_probe_resp_ie);
1027554c0a3aSHans de Goede 	pmlmepriv->wps_probe_resp_ie = NULL;
1028554c0a3aSHans de Goede 
1029f85ac230STeo Dacquet 	if (ie_len > 0) {
1030554c0a3aSHans de Goede 		pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
1031554c0a3aSHans de Goede 		pmlmepriv->wps_probe_resp_ie_len = ie_len;
1032e427bdd8SFabio Aiuto 		if (!pmlmepriv->wps_probe_resp_ie)
1033554c0a3aSHans de Goede 			return -EINVAL;
1034709c8e49SFabio Aiuto 
1035554c0a3aSHans de Goede 		memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
1036554c0a3aSHans de Goede 	}
1037554c0a3aSHans de Goede 
1038554c0a3aSHans de Goede 	return ret;
1039554c0a3aSHans de Goede }
1040554c0a3aSHans de Goede 
rtw_set_wps_assoc_resp(struct net_device * dev,struct ieee_param * param,int len)1041554c0a3aSHans de Goede static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
1042554c0a3aSHans de Goede {
1043554c0a3aSHans de Goede 	int ret = 0;
104442a18f09SIvan Safonov 	struct adapter *padapter = rtw_netdev_priv(dev);
1045722a3291SFranziska Naepelt 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1046554c0a3aSHans de Goede 	int ie_len;
1047554c0a3aSHans de Goede 
1048554c0a3aSHans de Goede 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
1049554c0a3aSHans de Goede 		return -EINVAL;
1050554c0a3aSHans de Goede 
1051554c0a3aSHans de Goede 	ie_len = len - 12 - 2;/*  12 = param header, 2:no packed */
1052554c0a3aSHans de Goede 
1053554c0a3aSHans de Goede 	kfree(pmlmepriv->wps_assoc_resp_ie);
1054554c0a3aSHans de Goede 	pmlmepriv->wps_assoc_resp_ie = NULL;
1055554c0a3aSHans de Goede 
1056f85ac230STeo Dacquet 	if (ie_len > 0) {
1057554c0a3aSHans de Goede 		pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
1058554c0a3aSHans de Goede 		pmlmepriv->wps_assoc_resp_ie_len = ie_len;
1059e427bdd8SFabio Aiuto 		if (!pmlmepriv->wps_assoc_resp_ie)
1060554c0a3aSHans de Goede 			return -EINVAL;
1061554c0a3aSHans de Goede 
1062554c0a3aSHans de Goede 		memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
1063554c0a3aSHans de Goede 	}
1064554c0a3aSHans de Goede 
1065554c0a3aSHans de Goede 	return ret;
1066554c0a3aSHans de Goede }
1067554c0a3aSHans de Goede 
rtw_set_hidden_ssid(struct net_device * dev,struct ieee_param * param,int len)1068554c0a3aSHans de Goede static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
1069554c0a3aSHans de Goede {
1070554c0a3aSHans de Goede 	int ret = 0;
107142a18f09SIvan Safonov 	struct adapter *adapter = rtw_netdev_priv(dev);
1072722a3291SFranziska Naepelt 	struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1073722a3291SFranziska Naepelt 	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
1074722a3291SFranziska Naepelt 	struct mlme_ext_info *mlmeinfo = &mlmeext->mlmext_info;
1075554c0a3aSHans de Goede 	int ie_len;
1076554c0a3aSHans de Goede 	u8 *ssid_ie;
1077554c0a3aSHans de Goede 	char ssid[NDIS_802_11_LENGTH_SSID + 1];
1078d495c550SMarco Cesati 	signed int ssid_len;
1079554c0a3aSHans de Goede 	u8 ignore_broadcast_ssid;
1080554c0a3aSHans de Goede 
1081554c0a3aSHans de Goede 	if (check_fwstate(mlmepriv, WIFI_AP_STATE) != true)
1082554c0a3aSHans de Goede 		return -EPERM;
1083554c0a3aSHans de Goede 
1084554c0a3aSHans de Goede 	if (param->u.bcn_ie.reserved[0] != 0xea)
1085554c0a3aSHans de Goede 		return -EINVAL;
1086554c0a3aSHans de Goede 
1087554c0a3aSHans de Goede 	mlmeinfo->hidden_ssid_mode = ignore_broadcast_ssid = param->u.bcn_ie.reserved[1];
1088554c0a3aSHans de Goede 
1089554c0a3aSHans de Goede 	ie_len = len - 12 - 2;/*  12 = param header, 2:no packed */
1090554c0a3aSHans de Goede 	ssid_ie = rtw_get_ie(param->u.bcn_ie.buf,  WLAN_EID_SSID, &ssid_len, ie_len);
1091554c0a3aSHans de Goede 
1092554c0a3aSHans de Goede 	if (ssid_ie && ssid_len > 0 && ssid_len <= NDIS_802_11_LENGTH_SSID) {
1093554c0a3aSHans de Goede 		struct wlan_bssid_ex *pbss_network = &mlmepriv->cur_network.network;
1094554c0a3aSHans de Goede 		struct wlan_bssid_ex *pbss_network_ext = &mlmeinfo->network;
1095554c0a3aSHans de Goede 
1096554c0a3aSHans de Goede 		memcpy(ssid, ssid_ie + 2, ssid_len);
1097554c0a3aSHans de Goede 		ssid[ssid_len] = 0x0;
1098554c0a3aSHans de Goede 
10996994aa43SFabio Aiuto 		memcpy(pbss_network->ssid.ssid, (void *)ssid, ssid_len);
11006994aa43SFabio Aiuto 		pbss_network->ssid.ssid_length = ssid_len;
11016994aa43SFabio Aiuto 		memcpy(pbss_network_ext->ssid.ssid, (void *)ssid, ssid_len);
11026994aa43SFabio Aiuto 		pbss_network_ext->ssid.ssid_length = ssid_len;
1103554c0a3aSHans de Goede 	}
1104554c0a3aSHans de Goede 
1105554c0a3aSHans de Goede 	return ret;
1106554c0a3aSHans de Goede }
1107554c0a3aSHans de Goede 
rtw_ioctl_acl_remove_sta(struct net_device * dev,struct ieee_param * param,int len)1108554c0a3aSHans de Goede static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
1109554c0a3aSHans de Goede {
111042a18f09SIvan Safonov 	struct adapter *padapter = rtw_netdev_priv(dev);
1111722a3291SFranziska Naepelt 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1112554c0a3aSHans de Goede 
1113554c0a3aSHans de Goede 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
1114554c0a3aSHans de Goede 		return -EINVAL;
1115554c0a3aSHans de Goede 
1116554c0a3aSHans de Goede 	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
1117554c0a3aSHans de Goede 	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
1118f85ac230STeo Dacquet 	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
1119554c0a3aSHans de Goede 		return -EINVAL;
1120554c0a3aSHans de Goede 	}
1121554c0a3aSHans de Goede 
11224769aae3SShobhit Kukreti 	rtw_acl_remove_sta(padapter, param->sta_addr);
11234769aae3SShobhit Kukreti 	return 0;
1124554c0a3aSHans de Goede }
1125554c0a3aSHans de Goede 
rtw_ioctl_acl_add_sta(struct net_device * dev,struct ieee_param * param,int len)1126554c0a3aSHans de Goede static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
1127554c0a3aSHans de Goede {
112842a18f09SIvan Safonov 	struct adapter *padapter = rtw_netdev_priv(dev);
1129722a3291SFranziska Naepelt 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1130554c0a3aSHans de Goede 
1131554c0a3aSHans de Goede 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
1132554c0a3aSHans de Goede 		return -EINVAL;
1133554c0a3aSHans de Goede 
1134554c0a3aSHans de Goede 	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
1135554c0a3aSHans de Goede 	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
1136f85ac230STeo Dacquet 	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
1137554c0a3aSHans de Goede 		return -EINVAL;
1138554c0a3aSHans de Goede 	}
1139554c0a3aSHans de Goede 
1140dedc1a73SHarsha Sharma 	return rtw_acl_add_sta(padapter, param->sta_addr);
1141554c0a3aSHans de Goede }
1142554c0a3aSHans de Goede 
rtw_ioctl_set_macaddr_acl(struct net_device * dev,struct ieee_param * param,int len)1143554c0a3aSHans de Goede static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
1144554c0a3aSHans de Goede {
1145554c0a3aSHans de Goede 	int ret = 0;
114642a18f09SIvan Safonov 	struct adapter *padapter = rtw_netdev_priv(dev);
1147722a3291SFranziska Naepelt 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1148554c0a3aSHans de Goede 
1149554c0a3aSHans de Goede 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
1150554c0a3aSHans de Goede 		return -EINVAL;
1151554c0a3aSHans de Goede 
1152554c0a3aSHans de Goede 	rtw_set_macaddr_acl(padapter, param->u.mlme.command);
1153554c0a3aSHans de Goede 
1154554c0a3aSHans de Goede 	return ret;
1155554c0a3aSHans de Goede }
1156554c0a3aSHans de Goede 
rtw_hostapd_ioctl(struct net_device * dev,struct iw_point * p)1157554c0a3aSHans de Goede static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
1158554c0a3aSHans de Goede {
1159554c0a3aSHans de Goede 	struct ieee_param *param;
1160554c0a3aSHans de Goede 	int ret = 0;
116142a18f09SIvan Safonov 	struct adapter *padapter = rtw_netdev_priv(dev);
1162554c0a3aSHans de Goede 
1163554c0a3aSHans de Goede 	/*
1164554c0a3aSHans de Goede 	 * this function is expect to call in master mode, which allows no power saving
1165554c0a3aSHans de Goede 	 * so, we just check hw_init_completed
1166554c0a3aSHans de Goede 	 */
1167554c0a3aSHans de Goede 
11689a4556bdSLarry Finger 	if (!padapter->hw_init_completed)
11699a4556bdSLarry Finger 		return -EPERM;
1170554c0a3aSHans de Goede 
11719a4556bdSLarry Finger 	if (!p->pointer || p->length != sizeof(*param))
11729a4556bdSLarry Finger 		return -EINVAL;
1173554c0a3aSHans de Goede 
11742ef2b7c2SJoe Perches 	param = rtw_malloc(p->length);
1175cd1f1450SMichael Straube 	if (!param)
11769a4556bdSLarry Finger 		return -ENOMEM;
1177554c0a3aSHans de Goede 
1178f85ac230STeo Dacquet 	if (copy_from_user(param, p->pointer, p->length)) {
1179428715baSAmitoj Kaur Chawla 		kfree(param);
11809a4556bdSLarry Finger 		return -EFAULT;
1181554c0a3aSHans de Goede 	}
1182554c0a3aSHans de Goede 
1183f85ac230STeo Dacquet 	switch (param->cmd) {
1184554c0a3aSHans de Goede 	case RTL871X_HOSTAPD_FLUSH:
1185554c0a3aSHans de Goede 
1186371ec021SHariprasad Kelam 		rtw_hostapd_sta_flush(dev);
1187554c0a3aSHans de Goede 
1188554c0a3aSHans de Goede 		break;
1189554c0a3aSHans de Goede 
1190554c0a3aSHans de Goede 	case RTL871X_HOSTAPD_ADD_STA:
1191554c0a3aSHans de Goede 
1192554c0a3aSHans de Goede 		ret = rtw_add_sta(dev, param);
1193554c0a3aSHans de Goede 
1194554c0a3aSHans de Goede 		break;
1195554c0a3aSHans de Goede 
1196554c0a3aSHans de Goede 	case RTL871X_HOSTAPD_REMOVE_STA:
1197554c0a3aSHans de Goede 
1198554c0a3aSHans de Goede 		ret = rtw_del_sta(dev, param);
1199554c0a3aSHans de Goede 
1200554c0a3aSHans de Goede 		break;
1201554c0a3aSHans de Goede 
1202554c0a3aSHans de Goede 	case RTL871X_HOSTAPD_SET_BEACON:
1203554c0a3aSHans de Goede 
1204554c0a3aSHans de Goede 		ret = rtw_set_beacon(dev, param, p->length);
1205554c0a3aSHans de Goede 
1206554c0a3aSHans de Goede 		break;
1207554c0a3aSHans de Goede 
1208554c0a3aSHans de Goede 	case RTL871X_SET_ENCRYPTION:
1209554c0a3aSHans de Goede 
1210554c0a3aSHans de Goede 		ret = rtw_set_encryption(dev, param, p->length);
1211554c0a3aSHans de Goede 
1212554c0a3aSHans de Goede 		break;
1213554c0a3aSHans de Goede 
1214554c0a3aSHans de Goede 	case RTL871X_HOSTAPD_GET_WPAIE_STA:
1215554c0a3aSHans de Goede 
1216554c0a3aSHans de Goede 		ret = rtw_get_sta_wpaie(dev, param);
1217554c0a3aSHans de Goede 
1218554c0a3aSHans de Goede 		break;
1219554c0a3aSHans de Goede 
1220554c0a3aSHans de Goede 	case RTL871X_HOSTAPD_SET_WPS_BEACON:
1221554c0a3aSHans de Goede 
1222554c0a3aSHans de Goede 		ret = rtw_set_wps_beacon(dev, param, p->length);
1223554c0a3aSHans de Goede 
1224554c0a3aSHans de Goede 		break;
1225554c0a3aSHans de Goede 
1226554c0a3aSHans de Goede 	case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
1227554c0a3aSHans de Goede 
1228554c0a3aSHans de Goede 		ret = rtw_set_wps_probe_resp(dev, param, p->length);
1229554c0a3aSHans de Goede 
1230554c0a3aSHans de Goede 		break;
1231554c0a3aSHans de Goede 
1232554c0a3aSHans de Goede 	case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
1233554c0a3aSHans de Goede 
1234554c0a3aSHans de Goede 		ret = rtw_set_wps_assoc_resp(dev, param, p->length);
1235554c0a3aSHans de Goede 
1236554c0a3aSHans de Goede 		break;
1237554c0a3aSHans de Goede 
1238554c0a3aSHans de Goede 	case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
1239554c0a3aSHans de Goede 
1240554c0a3aSHans de Goede 		ret = rtw_set_hidden_ssid(dev, param, p->length);
1241554c0a3aSHans de Goede 
1242554c0a3aSHans de Goede 		break;
1243554c0a3aSHans de Goede 
1244554c0a3aSHans de Goede 	case RTL871X_HOSTAPD_GET_INFO_STA:
1245554c0a3aSHans de Goede 
1246554c0a3aSHans de Goede 		ret = rtw_ioctl_get_sta_data(dev, param, p->length);
1247554c0a3aSHans de Goede 
1248554c0a3aSHans de Goede 		break;
1249554c0a3aSHans de Goede 
1250554c0a3aSHans de Goede 	case RTL871X_HOSTAPD_SET_MACADDR_ACL:
1251554c0a3aSHans de Goede 
1252554c0a3aSHans de Goede 		ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
1253554c0a3aSHans de Goede 
1254554c0a3aSHans de Goede 		break;
1255554c0a3aSHans de Goede 
1256554c0a3aSHans de Goede 	case RTL871X_HOSTAPD_ACL_ADD_STA:
1257554c0a3aSHans de Goede 
1258554c0a3aSHans de Goede 		ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
1259554c0a3aSHans de Goede 
1260554c0a3aSHans de Goede 		break;
1261554c0a3aSHans de Goede 
1262554c0a3aSHans de Goede 	case RTL871X_HOSTAPD_ACL_REMOVE_STA:
1263554c0a3aSHans de Goede 
1264554c0a3aSHans de Goede 		ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
1265554c0a3aSHans de Goede 
1266554c0a3aSHans de Goede 		break;
1267554c0a3aSHans de Goede 
1268554c0a3aSHans de Goede 	default:
1269554c0a3aSHans de Goede 		ret = -EOPNOTSUPP;
1270554c0a3aSHans de Goede 		break;
1271554c0a3aSHans de Goede 	}
1272554c0a3aSHans de Goede 
1273554c0a3aSHans de Goede 	if (ret == 0 && copy_to_user(p->pointer, param, p->length))
1274554c0a3aSHans de Goede 		ret = -EFAULT;
1275554c0a3aSHans de Goede 
1276428715baSAmitoj Kaur Chawla 	kfree(param);
1277554c0a3aSHans de Goede 	return ret;
1278554c0a3aSHans de Goede }
1279554c0a3aSHans de Goede 
1280554c0a3aSHans de Goede /*  copy from net/wireless/wext.c end */
1281554c0a3aSHans de Goede 
rtw_ioctl(struct net_device * dev,struct ifreq * rq,int cmd)1282554c0a3aSHans de Goede int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
1283554c0a3aSHans de Goede {
1284554c0a3aSHans de Goede 	struct iwreq *wrq = (struct iwreq *)rq;
1285554c0a3aSHans de Goede 	int ret = 0;
1286554c0a3aSHans de Goede 
1287f85ac230STeo Dacquet 	switch (cmd) {
1288554c0a3aSHans de Goede 	case RTL_IOCTL_WPA_SUPPLICANT:
1289554c0a3aSHans de Goede 		ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
1290554c0a3aSHans de Goede 		break;
1291554c0a3aSHans de Goede 	case RTL_IOCTL_HOSTAPD:
1292554c0a3aSHans de Goede 		ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
1293554c0a3aSHans de Goede 		break;
1294554c0a3aSHans de Goede 	default:
1295554c0a3aSHans de Goede 		ret = -EOPNOTSUPP;
1296554c0a3aSHans de Goede 		break;
1297554c0a3aSHans de Goede 	}
1298554c0a3aSHans de Goede 
1299554c0a3aSHans de Goede 	return ret;
1300554c0a3aSHans de Goede }
1301