All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] staging: rtl8188eu: Fix private WEXT IOCTL calls
@ 2017-11-23  1:29 ishraq.i.ashraf
  2017-11-23 13:24 ` Dan Carpenter
                   ` (5 more replies)
  0 siblings, 6 replies; 17+ messages in thread
From: ishraq.i.ashraf @ 2017-11-23  1:29 UTC (permalink / raw)
  To: gregkh
  Cc: himanshujha199640, goudapatilk, insafonov, devel, linux-kernel,
	Ishraq Ibne Ashraf

From: Ishraq Ibne Ashraf <ishraq.i.ashraf@gmail.com>

Commit 8bfb36766064 ("wireless: wext: remove ndo_do_ioctl fallback") breaks private WEXT
IOCTL calls of this driver as these are not invoked through ndo_do_ioctl
interface anymore. As a result hostapd stops working with this driver. In
this patch this problem is solved by implementing equivalent private IOCTL
functions of the existing ones which are accessed via iw_handler_def
interface.

Signed-off-by: Ishraq Ibne Ashraf <ishraq.i.ashraf@gmail.com>
---
 drivers/staging/rtl8188eu/os_dep/ioctl_linux.c | 1042 ++++++++++++++++++++++++
 1 file changed, 1042 insertions(+)

diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
index c0664dc..7503751 100644
--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
@@ -3061,6 +3061,1046 @@ static iw_handler rtw_handlers[] = {
 	NULL,					/*---hole---*/
 };
 
+static int get_private_handler_ieee_param(struct adapter *padapter,
+	union iwreq_data *wrqu,
+	void *param)
+{
+	/*
+	 * This function is expected to be called in master mode, which allows no
+	 * power saving. So we just check hw_init_completed.
+	 */
+
+	if (!padapter->hw_init_completed)
+		return -EPERM;
+
+	if (!wrqu->data.pointer)
+		return -EINVAL;
+
+	/*
+	 * Since we don't allocate memory for param in this function, we assume
+	 * the caller of this function will properly allocate and deallocate memory
+	 * for param.
+	 */
+	if (copy_from_user(param, wrqu->data.pointer, wrqu->data.length))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int rtw_hostapd_sta_flush_pvt(struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra)
+{
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+	DBG_88E("%s\n", __func__);
+
+	flush_all_cam_entry(padapter); // Clear CAM.
+
+	return rtw_sta_flush(padapter);
+}
+
+static int rtw_add_sta_pvt(struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra)
+{
+	int ret = 0;
+	struct sta_info *psta = NULL;
+	struct ieee_param *param = NULL;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
+
+	if (!param) {
+		DBG_88E(" rtw_add_sta: ieee_param allocate fail !!!\n");
+
+		return -ENOMEM;
+	}
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+
+	if (ret != 0) {
+		kfree(param);
+		DBG_88E(" rtw_add_sta: ieee_param get fail !!!\n");
+
+		return ret;
+	}
+
+	DBG_88E("rtw_add_sta(aid =%d) =%pM\n", param->u.add_sta.aid, (param->sta_addr));
+
+	if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)))
+		return -EINVAL;
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
+	      return -EINVAL;
+
+	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+	if (psta) {
+		int flags = param->u.add_sta.flags;
+		psta->aid = param->u.add_sta.aid; // aid = 1~2007.
+
+		memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
+
+		// Check WMM cap.
+		if (WLAN_STA_WME&flags)
+			psta->qos_option = 1;
+		else
+			psta->qos_option = 0;
+
+		if (pmlmepriv->qospriv.qos_option == 0)
+			psta->qos_option = 0;
+
+		// Check 802.11n HT cap.
+		if (WLAN_STA_HT&flags) {
+			psta->htpriv.ht_option = true;
+			psta->qos_option = 1;
+			memcpy(&psta->htpriv.ht_cap,
+			       &param->u.add_sta.ht_cap,
+			       sizeof(struct ieee80211_ht_cap));
+		} else {
+			psta->htpriv.ht_option = false;
+		}
+
+		if (pmlmepriv->htpriv.ht_option == false)
+			psta->htpriv.ht_option = false;
+
+		update_sta_info_apmode(padapter, psta);
+	} else {
+		ret = -ENOMEM;
+	}
+
+	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+		ret = -EFAULT;
+
+	return ret;
+}
+
+static int rtw_del_sta_pvt(struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra)
+{
+	int ret = 0;
+	struct sta_info *psta = NULL;
+	struct ieee_param *param = NULL;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	int updated = 0;
+
+	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
+
+	if (!param) {
+		DBG_88E(" rtw_del_sta: ieee_param allocate fail !!!\n");
+
+		return -ENOMEM;
+	}
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+
+	if (ret != 0) {
+		kfree(param);
+		DBG_88E(" rtw_del_sta: ieee_param get fail !!!\n");
+
+		return ret;
+	}
+
+	DBG_88E("rtw_del_sta =%pM\n", (param->sta_addr));
+
+	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
+		return -EINVAL;
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
+	      return -EINVAL;
+
+	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+	if (psta) {
+		spin_lock_bh(&pstapriv->asoc_list_lock);
+		if (!list_empty(&psta->asoc_list)) {
+			list_del_init(&psta->asoc_list);
+			pstapriv->asoc_list_cnt--;
+			updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
+		}
+		spin_unlock_bh(&pstapriv->asoc_list_lock);
+		associated_clients_update(padapter, updated);
+		psta = NULL;
+	} else {
+		DBG_88E("rtw_del_sta(), sta has already been removed or never been added\n");
+	}
+
+	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+		ret = -EFAULT;
+
+	return ret;
+}
+
+static int rtw_set_beacon_pvt(struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra)
+{
+	int ret = 0;
+	int len = 0;
+	unsigned char *pbuf = NULL;
+	struct ieee_param *param = NULL;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
+
+	if (!param) {
+		DBG_88E(" rtw_set_beacon: ieee_param allocate fail !!!\n");
+
+		return -ENOMEM;
+	}
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+
+	if (ret != 0) {
+		kfree(param);
+		DBG_88E(" rtw_set_beacon: ieee_param get fail !!!\n");
+
+		return ret;
+	}
+
+	len = wrqu->data.length;
+	pbuf = param->u.bcn_ie.buf;
+
+	DBG_88E("%s, len =%d\n", __func__, len);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
+		return -EINVAL;
+
+	memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
+
+	if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
+		pstapriv->max_num_sta = NUM_STA;
+
+	if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) == _SUCCESS) //  12 = Param header, 2 = Not packed.
+		ret = 0;
+	else
+		ret = -EINVAL;
+
+	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+		ret = -EFAULT;
+
+	return ret;
+}
+
+static int rtw_set_encryption_pvt(struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra)
+{
+	int ret = 0;
+	int param_len = 0;
+	struct ieee_param *param = NULL;
+	u32 wep_key_idx, wep_key_len, wep_total_len;
+	struct ndis_802_11_wep	 *pwep = NULL;
+	struct sta_info *psta = NULL, *pbcmc_sta = NULL;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct security_priv *psecuritypriv = &(padapter->securitypriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
+
+	if (!param) {
+		ret = -ENOMEM;
+		DBG_88E(" r871x_set_encryption: ieee_param allocate fail !!!\n");
+
+		goto exit;
+	}
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+
+	if (ret != 0) {
+		kfree(param);
+		DBG_88E(" r871x_set_encryption: ieee_param get fail !!!\n");
+
+		goto exit;
+	}
+
+	param_len = wrqu->data.length;
+
+	DBG_88E("%s\n", __func__);
+	param->u.crypt.err = 0;
+	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
+	if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {
+		ret =  -EINVAL;
+		goto exit;
+	}
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		if (param->u.crypt.idx >= WEP_KEYS) {
+			ret = -EINVAL;
+			goto exit;
+		}
+	} else {
+		psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+		if (!psta) {
+			DBG_88E("rtw_set_encryption(), sta has already been removed or never been added\n");
+			goto exit;
+		}
+	}
+
+	if (strcmp(param->u.crypt.alg, "none") == 0 && (!psta)) {
+		// TODO: Clear default encryption keys.
+
+		DBG_88E("clear default encryption keys, keyid =%d\n", param->u.crypt.idx);
+		goto exit;
+	}
+	if (strcmp(param->u.crypt.alg, "WEP") == 0 && (!psta)) {
+		DBG_88E("r871x_set_encryption, crypt.alg = WEP\n");
+		wep_key_idx = param->u.crypt.idx;
+		wep_key_len = param->u.crypt.key_len;
+		DBG_88E("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);
+		if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
+			ret = -EINVAL;
+			goto exit;
+		}
+
+		if (wep_key_len > 0) {
+			wep_key_len = wep_key_len <= 5 ? 5 : 13;
+			wep_total_len = wep_key_len + offsetof(struct ndis_802_11_wep, KeyMaterial);
+			pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len);
+			if (!pwep) {
+				DBG_88E(" r871x_set_encryption: pwep allocate fail !!!\n");
+				goto exit;
+			}
+
+			memset(pwep, 0, wep_total_len);
+
+			pwep->KeyLength = wep_key_len;
+			pwep->Length = wep_total_len;
+		}
+
+		pwep->KeyIndex = wep_key_idx;
+
+		memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
+
+		if (param->u.crypt.set_tx) {
+			DBG_88E("wep, set_tx = 1\n");
+
+			psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
+			psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
+			psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+
+			if (pwep->KeyLength == 13) {
+				psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
+				psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+			}
+
+			psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
+
+			memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]),
+			       pwep->KeyMaterial,
+			       pwep->KeyLength);
+
+			psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
+
+			set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
+		} else {
+			DBG_88E("wep, set_tx = 0\n");
+
+			/*
+			 * Don't update "psecuritypriv->dot11PrivacyAlgrthm" and
+			 * "psecuritypriv->dot11PrivacyKeyIndex = keyid", but rtw_set_key()
+			 * can to cam.
+			 */
+
+			memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]),
+			       pwep->KeyMaterial,
+			       pwep->KeyLength);
+
+			psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
+
+			set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
+		}
+
+		goto exit;
+	}
+
+	if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { //  Group key.
+		if (param->u.crypt.set_tx == 1) {
+			if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+				DBG_88E("%s, set group_key, WEP\n", __func__);
+
+				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+				       param->u.crypt.key,
+				       min_t(u16, param->u.crypt.key_len,
+				       16));
+
+				psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+				if (param->u.crypt.key_len == 13)
+						psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+			} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+				DBG_88E("%s, set group_key, TKIP\n", __func__);
+				psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
+				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+				       param->u.crypt.key,
+				       min_t(u16, param->u.crypt.key_len,
+				       16));
+				// Set mic key.
+				memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey,
+				       &(param->u.crypt.key[16]),
+				       8);
+				memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey,
+				       &(param->u.crypt.key[24]),
+				       8);
+
+				psecuritypriv->busetkipkey = true;
+			} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+				DBG_88E("%s, set group_key, CCMP\n", __func__);
+				psecuritypriv->dot118021XGrpPrivacy = _AES_;
+				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+				       param->u.crypt.key,
+				       min_t(u16, param->u.crypt.key_len, 16));
+			} else {
+				DBG_88E("%s, set group_key, none\n", __func__);
+				psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+			}
+			psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
+			psecuritypriv->binstallGrpkey = true;
+			psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;
+			set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
+			pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+			if (pbcmc_sta) {
+				pbcmc_sta->ieee8021x_blocked = false;
+				pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; // rx will use bmc_sta's dot118021XPrivacy.
+			}
+		}
+		goto exit;
+	}
+
+	if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { // psk/802_1x.
+		if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+			if (param->u.crypt.set_tx == 1) {
+				memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
+
+				if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+					DBG_88E("%s, set pairwise key, WEP\n", __func__);
+
+					psta->dot118021XPrivacy = _WEP40_;
+					if (param->u.crypt.key_len == 13)
+						psta->dot118021XPrivacy = _WEP104_;
+				} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+					DBG_88E("%s, set pairwise key, TKIP\n", __func__);
+
+					psta->dot118021XPrivacy = _TKIP_;
+
+					// Set mic key.
+					memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
+					memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
+
+					psecuritypriv->busetkipkey = true;
+				} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+					DBG_88E("%s, set pairwise key, CCMP\n", __func__);
+
+					psta->dot118021XPrivacy = _AES_;
+				} else {
+					DBG_88E("%s, set pairwise key, none\n", __func__);
+
+					psta->dot118021XPrivacy = _NO_PRIVACY_;
+				}
+
+				set_pairwise_key(padapter, psta);
+
+				psta->ieee8021x_blocked = false;
+			} else { // Group key ?
+				if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+					       param->u.crypt.key,
+					       min_t(u16, param->u.crypt.key_len, 16));
+					psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+					if (param->u.crypt.key_len == 13)
+						psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+				} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+					psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
+
+					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+					       param->u.crypt.key,
+					       min_t(u16, param->u.crypt.key_len, 16));
+
+					// Set mic key.
+					memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey,
+					       &(param->u.crypt.key[16]), 8);
+					memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey,
+					       &(param->u.crypt.key[24]), 8);
+
+					psecuritypriv->busetkipkey = true;
+				} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+					psecuritypriv->dot118021XGrpPrivacy = _AES_;
+
+					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+					       param->u.crypt.key,
+					       min_t(u16, param->u.crypt.key_len, 16));
+				} else {
+					psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+				}
+
+				psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
+				psecuritypriv->binstallGrpkey = true;
+				psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;
+
+				set_group_key(padapter,
+					param->u.crypt.key,
+					psecuritypriv->dot118021XGrpPrivacy,
+					param->u.crypt.idx);
+
+				pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+				if (pbcmc_sta) {
+					pbcmc_sta->ieee8021x_blocked = false;
+					pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; // rx will use bmc_sta's dot118021XPrivacy.
+				}
+			}
+		}
+	}
+
+exit:
+
+	kfree(pwep);
+
+	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+		ret = -EFAULT;
+
+	return ret;
+}
+
+static int rtw_get_sta_wpaie_pvt(struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra)
+{
+	int ret = 0;
+	struct sta_info *psta = NULL;
+	struct ieee_param *param = NULL;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
+
+	if (!param) {
+		DBG_88E(" rtw_get_sta_wpaie: ieee_param allocate fail !!!\n");
+
+		return -ENOMEM;
+	}
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+
+	if (ret != 0) {
+		kfree(param);
+		DBG_88E(" rtw_get_sta_wpaie: ieee_param get fail !!!\n");
+
+		return ret;
+	}
+
+	DBG_88E("rtw_get_sta_wpaie, sta_addr: %pM\n", (param->sta_addr));
+
+	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
+		return -EINVAL;
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
+	      return -EINVAL;
+
+	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+	if (psta) {
+		if (psta->wpa_ie[0] == WLAN_EID_RSN ||
+		    psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
+		      int wpa_ie_len;
+		      int copy_len;
+
+		      wpa_ie_len = psta->wpa_ie[1];
+		      copy_len = min_t(int, wpa_ie_len + 2, sizeof(psta->wpa_ie));
+		      param->u.wpa_ie.len = copy_len;
+		      memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
+		} else {
+			DBG_88E("sta's wpa_ie is NONE\n");
+		}
+	} else {
+		ret = -1;
+	}
+
+	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+		ret = -EFAULT;
+
+	return ret;
+}
+
+static int rtw_set_wps_beacon_pvt(struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra)
+{
+	int ret = 0;
+	struct ieee_param *param = NULL;
+	unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	int len, ie_len;
+
+	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
+
+	if (!param) {
+		DBG_88E(" rtw_set_wps_beacon: ieee_param allocate fail !!!\n");
+
+		return  -ENOMEM;
+	}
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+
+	if (ret != 0) {
+		kfree(param);
+		DBG_88E(" rtw_set_wps_beacon: ieee_param get fail !!!\n");
+
+		return ret;
+	}
+
+	len = wrqu->data.length;
+
+	DBG_88E("%s, len =%d\n", __func__, len);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
+		return -EINVAL;
+
+	ie_len = len-12-2; // 12 = Param header, 2 = Not packed.
+
+	kfree(pmlmepriv->wps_beacon_ie);
+	pmlmepriv->wps_beacon_ie = NULL;
+
+	if (ie_len > 0) {
+		pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
+		pmlmepriv->wps_beacon_ie_len = ie_len;
+		if (!pmlmepriv->wps_beacon_ie) {
+			DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+			return -EINVAL;
+		}
+
+		memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
+		update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
+
+		pmlmeext->bstart_bss = true;
+	}
+
+	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+		ret = -EFAULT;
+
+	return ret;
+}
+
+static int rtw_set_wps_probe_resp_pvt(struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra)
+{
+	int ret = 0;
+	struct ieee_param *param = NULL;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	int len, ie_len;
+
+	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
+
+	if (!param) {
+		DBG_88E(" rtw_set_wps_probe_resp: ieee_param allocate fail !!!\n");
+
+		return -ENOMEM;
+	}
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+
+	if (ret != 0) {
+		kfree(param);
+		DBG_88E(" rtw_set_wps_probe_resp: ieee_param get fail !!!\n");
+
+		return ret;
+	}
+
+	len = wrqu->data.length;
+
+	DBG_88E("%s, len =%d\n", __func__, len);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
+		return -EINVAL;
+
+	ie_len = len-12-2; // 12 = Param header, 2 = Not packed.
+
+	kfree(pmlmepriv->wps_probe_resp_ie);
+	pmlmepriv->wps_probe_resp_ie = NULL;
+
+	if (ie_len > 0) {
+		pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
+		pmlmepriv->wps_probe_resp_ie_len = ie_len;
+		if (!pmlmepriv->wps_probe_resp_ie) {
+			DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+			return -EINVAL;
+		}
+		memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
+	}
+
+	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+		ret = -EFAULT;
+
+	return ret;
+}
+
+static int rtw_set_wps_assoc_resp_pvt(struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra)
+{
+	int ret = 0;
+	struct ieee_param *param = NULL;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	int len, ie_len;
+
+	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
+
+	if (!param) {
+		DBG_88E(" rtw_set_wps_assoc_resp: ieee_param allocate fail !!!\n");
+
+		return -ENOMEM;
+	}
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+
+	if (ret != 0) {
+		kfree(param);
+		DBG_88E(" rtw_set_wps_assoc_resp: ieee_param get fail !!!\n");
+
+		return ret;
+	}
+
+	len = wrqu->data.length;
+
+	DBG_88E("%s, len =%d\n", __func__, len);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
+		return -EINVAL;
+
+	ie_len = len-12-2; // 12 = Param header, 2 = Not packed.
+
+	kfree(pmlmepriv->wps_assoc_resp_ie);
+	pmlmepriv->wps_assoc_resp_ie = NULL;
+
+	if (ie_len > 0) {
+		pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
+		pmlmepriv->wps_assoc_resp_ie_len = ie_len;
+		if (!pmlmepriv->wps_assoc_resp_ie) {
+			DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+			return -EINVAL;
+		}
+
+		memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
+	}
+
+	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+		ret = -EFAULT;
+
+	return ret;
+}
+
+static int rtw_set_hidden_ssid_pvt(struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra)
+{
+	int ret = 0;
+	struct ieee_param *param = NULL;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	u8 value;
+
+	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
+
+	if (!param) {
+		DBG_88E(" rtw_set_hidden_ssid: ieee_param allocate fail !!!\n");
+
+		return -ENOMEM;
+	}
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+
+	if (ret != 0) {
+		kfree(param);
+		DBG_88E(" rtw_set_hidden_ssid: ieee_param get fail !!!\n");
+
+		return ret;
+	}
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
+		return -EINVAL;
+
+	if (param->u.wpa_param.name != 0) // Dummy test.
+		DBG_88E("%s name(%u) != 0\n", __func__, param->u.wpa_param.name);
+	value = param->u.wpa_param.value;
+
+	// Use the same definition of hostapd's ignore_broadcast_ssid.
+	if (value != 1 && value != 2)
+		value = 0;
+	DBG_88E("%s value(%u)\n", __func__, value);
+	pmlmeinfo->hidden_ssid_mode = value;
+
+	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+		ret = -EFAULT;
+
+	return ret;
+}
+
+static int rtw_ioctl_get_sta_data_pvt(struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra)
+{
+	int ret = 0;
+	struct sta_info *psta = NULL;
+	struct sta_data *psta_data = NULL;
+	struct ieee_param_ex *param_ex = NULL;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	param_ex = (struct ieee_param_ex *)rtw_malloc(wrqu->data.length);
+
+	if (!param_ex) {
+		DBG_88E(" rtw_ioctl_get_sta_data: ieee_param_ex allocate fail !!!\n");
+
+		return -ENOMEM;
+	}
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param_ex);
+
+	if (ret != 0) {
+		kfree(param_ex);
+		DBG_88E(" rtw_ioctl_get_sta_data: ieee_param get fail !!!\n");
+
+		return ret;
+	}
+
+	psta_data = (struct sta_data *)param_ex->data;
+
+	DBG_88E("rtw_ioctl_get_sta_info, sta_addr: %pM\n", (param_ex->sta_addr));
+
+	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
+		return -EINVAL;
+
+	if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
+	    param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
+	    param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff)
+	      return -EINVAL;
+
+	psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
+	if (psta) {
+		psta_data->aid = (u16)psta->aid;
+		psta_data->capability = psta->capability;
+		psta_data->flags = psta->flags;
+
+		/*
+		nonerp_set : BIT(0)
+		no_short_slot_time_set : BIT(1)
+		no_short_preamble_set : BIT(2)
+		no_ht_gf_set : BIT(3)
+		no_ht_set : BIT(4)
+		ht_20mhz_set : BIT(5)
+		*/
+
+		psta_data->sta_set = \
+			((psta->nonerp_set) |
+			(psta->no_short_slot_time_set << 1) |
+			(psta->no_short_preamble_set << 2) |
+			(psta->no_ht_gf_set << 3) |
+			(psta->no_ht_set << 4) |
+			(psta->ht_20mhz_set << 5));
+		psta_data->tx_supp_rates_len =  psta->bssratelen;
+		memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
+		memcpy(&psta_data->ht_cap,
+		       &psta->htpriv.ht_cap,
+		       sizeof(struct ieee80211_ht_cap));
+		psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
+		psta_data->rx_bytes = psta->sta_stats.rx_bytes;
+		psta_data->rx_drops = psta->sta_stats.rx_drops;
+		psta_data->tx_pkts = psta->sta_stats.tx_pkts;
+		psta_data->tx_bytes = psta->sta_stats.tx_bytes;
+		psta_data->tx_drops = psta->sta_stats.tx_drops;
+	} else {
+		ret = -1;
+	}
+
+	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param_ex, wrqu->data.length)))
+		ret = -EFAULT;
+
+	return ret;
+}
+
+static int rtw_ioctl_set_macaddr_acl_pvt(struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra)
+{
+	int ret = 0;
+	struct ieee_param *param = NULL;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
+
+	if (!param) {
+		DBG_88E(" rtw_ioctl_set_macaddr_acl: ieee_param allocate fail !!!\n");
+
+		return -ENOMEM;
+	}
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+
+	if (ret != 0) {
+		kfree(param);
+		DBG_88E(" rtw_ioctl_set_macaddr_acl: ieee_param get fail !!!\n");
+
+		return ret;
+	}
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
+		return -EINVAL;
+
+	rtw_set_macaddr_acl(padapter, param->u.mlme.command);
+
+	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+		ret = -EFAULT;
+
+	return ret;
+}
+
+static int rtw_ioctl_acl_add_sta_pvt(struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra)
+{
+	int ret = 0;
+	struct ieee_param *param = NULL;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
+
+	if (!param) {
+		DBG_88E(" rtw_ioctl_acl_add_sta: ieee_param allocate fail !!!\n");
+
+		return -ENOMEM;
+	}
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+
+	if (ret != 0) {
+		kfree(param);
+		DBG_88E(" rtw_ioctl_acl_add_sta: ieee_param get fail !!!\n");
+
+		return ret;
+	}
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
+		return -EINVAL;
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
+	      return -EINVAL;
+
+	ret = rtw_acl_add_sta(padapter, param->sta_addr);
+
+	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+		ret = -EFAULT;
+
+	return ret;
+}
+
+static int rtw_ioctl_acl_remove_sta_pvt(struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra)
+{
+	int ret = 0;
+	struct ieee_param *param = NULL;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
+
+	if (!param) {
+		DBG_88E(" rtw_ioctl_acl_remove_sta: ieee_param allocate fail !!!\n");
+
+		return -ENOMEM;
+	}
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+
+	if (ret != 0) {
+		kfree(param);
+		DBG_88E(" rtw_ioctl_acl_remove_sta: ieee_param get fail !!!\n");
+
+		return ret;
+	}
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
+		return -EINVAL;
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
+	      return -EINVAL;
+
+	ret = rtw_acl_remove_sta(padapter, param->sta_addr);
+
+	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+		ret = -EFAULT;
+
+	return ret;
+}
+
+static iw_handler rtw_handlers_private[] = {
+	NULL,                          // Empty
+	rtw_hostapd_sta_flush_pvt,     // RTL871X_HOSTAPD_FLUSH
+	rtw_add_sta_pvt,               // RTL871X_HOSTAPD_ADD_STA
+	rtw_del_sta_pvt,               // RTL871X_HOSTAPD_REMOVE_STA
+	rtw_ioctl_get_sta_data_pvt,    // RTL871X_HOSTAPD_GET_INFO_STA
+	rtw_get_sta_wpaie_pvt,         // RTL871X_HOSTAPD_GET_WPAIE_STA
+	rtw_set_encryption_pvt,        // RTL871X_SET_ENCRYPTION
+	NULL,                          // RTL871X_GET_ENCRYPTION
+	NULL,                          // RTL871X_HOSTAPD_SET_FLAGS_STA
+	NULL,                          // RTL871X_HOSTAPD_GET_RID
+	NULL,                          // RTL871X_HOSTAPD_SET_RID
+	NULL,                          // RTL871X_HOSTAPD_SET_ASSOC_AP_ADDR
+	NULL,                          // RTL871X_HOSTAPD_SET_GENERIC_ELEMENT
+	NULL,                          // RTL871X_HOSTAPD_MLME
+	NULL,                          // RTL871X_HOSTAPD_SCAN_REQ
+	NULL,                          // RTL871X_HOSTAPD_STA_CLEAR_STATS
+	rtw_set_beacon_pvt,            // RTL871X_HOSTAPD_SET_BEACON
+	rtw_set_wps_beacon_pvt,        // RTL871X_HOSTAPD_SET_WPS_BEACON
+	rtw_set_wps_probe_resp_pvt,    // RTL871X_HOSTAPD_SET_WPS_PROBE_RESP
+	rtw_set_wps_assoc_resp_pvt,    // RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP
+	rtw_set_hidden_ssid_pvt,       // RTL871X_HOSTAPD_SET_HIDDEN_SSID
+	rtw_ioctl_set_macaddr_acl_pvt, // RTL871X_HOSTAPD_SET_MACADDR_ACL
+	rtw_ioctl_acl_add_sta_pvt,     // RTL871X_HOSTAPD_ACL_ADD_STA
+	rtw_ioctl_acl_remove_sta_pvt,  // RTL871X_HOSTAPD_ACL_REMOVE_STA
+};
+
 static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
 {
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
@@ -3089,6 +4129,8 @@ static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
 struct iw_handler_def rtw_handlers_def = {
 	.standard = rtw_handlers,
 	.num_standard = ARRAY_SIZE(rtw_handlers),
+	.private = rtw_handlers_private,
+	.num_private = ARRAY_SIZE(rtw_handlers_private),
 	.get_wireless_stats = rtw_get_wireless_stats,
 };
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH] staging: rtl8188eu: Fix private WEXT IOCTL calls
  2017-11-23  1:29 [PATCH] staging: rtl8188eu: Fix private WEXT IOCTL calls ishraq.i.ashraf
@ 2017-11-23 13:24 ` Dan Carpenter
  2017-11-25  0:52 ` [PATCH 2/2] " ishraq.i.ashraf
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: Dan Carpenter @ 2017-11-23 13:24 UTC (permalink / raw)
  To: ishraq.i.ashraf
  Cc: gregkh, devel, insafonov, goudapatilk, linux-kernel,
	himanshujha199640, Johannes Berg

On Thu, Nov 23, 2017 at 02:29:06AM +0100, ishraq.i.ashraf@gmail.com wrote:
> From: Ishraq Ibne Ashraf <ishraq.i.ashraf@gmail.com>
> 
> Commit 8bfb36766064 ("wireless: wext: remove ndo_do_ioctl fallback") breaks private WEXT
> IOCTL calls of this driver as these are not invoked through ndo_do_ioctl
> interface anymore. As a result hostapd stops working with this driver. In
> this patch this problem is solved by implementing equivalent private IOCTL
> functions of the existing ones which are accessed via iw_handler_def
> interface.
> 
> Signed-off-by: Ishraq Ibne Ashraf <ishraq.i.ashraf@gmail.com>


It's great to fix this, but new code should be at normal kernel quality.

> ---
>  drivers/staging/rtl8188eu/os_dep/ioctl_linux.c | 1042 ++++++++++++++++++++++++
>  1 file changed, 1042 insertions(+)
> 
> diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
> index c0664dc..7503751 100644
> --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
> +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
> @@ -3061,6 +3061,1046 @@ static iw_handler rtw_handlers[] = {
>  	NULL,					/*---hole---*/
>  };
>  
> +static int get_private_handler_ieee_param(struct adapter *padapter,
> +	union iwreq_data *wrqu,
> +	void *param)

Indent these more.

> +{
> +	/*
> +	 * This function is expected to be called in master mode, which allows no
> +	 * power saving. So we just check hw_init_completed.
> +	 */
> +
> +	if (!padapter->hw_init_completed)
> +		return -EPERM;
> +
> +	if (!wrqu->data.pointer)
> +		return -EINVAL;

You could leave this out and it will return -EFAULT when copy_from_user()
fails.  That's probably the right error code.

> +
> +	/*
> +	 * Since we don't allocate memory for param in this function, we assume
> +	 * the caller of this function will properly allocate and deallocate memory
> +	 * for param.
> +	 */

This is an obvious comment.  Remove it.

> +	if (copy_from_user(param, wrqu->data.pointer, wrqu->data.length))
> +		return -EFAULT;
> +
> +	return 0;
> +}
> +
> +static int rtw_hostapd_sta_flush_pvt(struct net_device *dev,
> +	struct iw_request_info *info,
> +	union iwreq_data *wrqu,
> +	char *extra)
> +{
> +	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
> +
> +	DBG_88E("%s\n", __func__);

Remove this line.

> +
> +	flush_all_cam_entry(padapter); // Clear CAM.

Comment style.

> +
> +	return rtw_sta_flush(padapter);
> +}
> +
> +static int rtw_add_sta_pvt(struct net_device *dev,
> +	struct iw_request_info *info,
> +	union iwreq_data *wrqu,
> +	char *extra)
> +{
> +	int ret = 0;
> +	struct sta_info *psta = NULL;
> +	struct ieee_param *param = NULL;

Don't initialize these to useless values.  It turns off the static
checker for finding uninitialized variables.

> +	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
> +	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
> +	struct sta_priv *pstapriv = &padapter->stapriv;
> +
> +	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);

rtw_malloc() is buggy.  It ignores locking.  Let's not use it in new
code.

> +
> +	if (!param) {
> +		DBG_88E(" rtw_add_sta: ieee_param allocate fail !!!\n");

No need to print this debug message.

> +
> +		return -ENOMEM;
> +	}
> +
> +	ret = get_private_handler_ieee_param(padapter, wrqu, param);
> +
> +	if (ret != 0) {

if (ret).  "ret" isn't a number zero which can be used for math like
"ret + 2", it's an error code.  The != 0 is a double negative which
hurts readability.  != 0 is appropriate for numbers and strcmp()
functions.

> +		kfree(param);

Free this at the end of the function.

> +		DBG_88E(" rtw_add_sta: ieee_param get fail !!!\n");

These messages are so ugly !!!

> +
> +		return ret;
> +	}
> +
> +	DBG_88E("rtw_add_sta(aid =%d) =%pM\n", param->u.add_sta.aid, (param->sta_addr));
> +
> +	if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)))
> +		return -EINVAL;

		ret = -EINVAL;
		goto err_free_param;

> +
> +	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
> +	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
> +	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
> +	      return -EINVAL;

		ret = -EINVAL;
		goto err_free_param;


> +
> +	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
> +	if (psta) {

Always do failure handling.  Never do success handling.  So this becomes:

	if (!psta)
		goto err_free_param;



> +		int flags = param->u.add_sta.flags;
> +		psta->aid = param->u.add_sta.aid; // aid = 1~2007.
> +
> +		memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
> +
> +		// Check WMM cap.

Comment style

> +		if (WLAN_STA_WME&flags)
> +			psta->qos_option = 1;
> +		else
> +			psta->qos_option = 0;
> +
> +		if (pmlmepriv->qospriv.qos_option == 0)
> +			psta->qos_option = 0;
> +
> +		// Check 802.11n HT cap.
> +		if (WLAN_STA_HT&flags) {
> +			psta->htpriv.ht_option = true;
> +			psta->qos_option = 1;
> +			memcpy(&psta->htpriv.ht_cap,
> +			       &param->u.add_sta.ht_cap,
> +			       sizeof(struct ieee80211_ht_cap));
> +		} else {
> +			psta->htpriv.ht_option = false;
> +		}
> +
> +		if (pmlmepriv->htpriv.ht_option == false)
> +			psta->htpriv.ht_option = false;
> +
> +		update_sta_info_apmode(padapter, psta);
> +	} else {
> +		ret = -ENOMEM;
> +	}
> +
> +	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
> +		ret = -EFAULT;

We need to free param.

> +
> +	return ret;


The end of the function could look like this:

	update_sta_info_apmode(padapter, psta);

	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
		ret = -EFAULT;

err_free_param:
	kfree(param);

	return ret;


> +}
> +
> +static int rtw_del_sta_pvt(struct net_device *dev,
> +	struct iw_request_info *info,
> +	union iwreq_data *wrqu,
> +	char *extra)
> +{
> +	int ret = 0;
> +	struct sta_info *psta = NULL;
> +	struct ieee_param *param = NULL;

Remove initialization.

> +	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
> +	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
> +	struct sta_priv *pstapriv = &padapter->stapriv;
> +	int updated = 0;
> +
> +	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);

Use kmalloc();  Basically all the same stuff as the previous function.

regards,
dan carpenter

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 2/2] staging: rtl8188eu: Fix private WEXT IOCTL calls
  2017-11-23  1:29 [PATCH] staging: rtl8188eu: Fix private WEXT IOCTL calls ishraq.i.ashraf
  2017-11-23 13:24 ` Dan Carpenter
@ 2017-11-25  0:52 ` ishraq.i.ashraf
  2017-11-25  4:40   ` Dan Carpenter
  2017-11-25  1:29 ` [PATCH v2] " ishraq.i.ashraf
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: ishraq.i.ashraf @ 2017-11-25  0:52 UTC (permalink / raw)
  To: gregkh
  Cc: himanshujha199640, goudapatilk, insafonov, dan.carpenter, devel,
	linux-kernel, Ishraq Ibne Ashraf

From: Ishraq Ibne Ashraf <ishraq.i.ashraf@gmail.com>

Apply changes suggested by Dan Carpenter
---
 drivers/staging/rtl8188eu/os_dep/ioctl_linux.c | 1052 ++++++++++++------------
 1 file changed, 536 insertions(+), 516 deletions(-)

diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
index 7503751..e871344 100644
--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
@@ -3062,25 +3062,16 @@ static iw_handler rtw_handlers[] = {
 };
 
 static int get_private_handler_ieee_param(struct adapter *padapter,
-	union iwreq_data *wrqu,
-	void *param)
+					  union iwreq_data *wrqu,
+					  void *param)
 {
 	/*
 	 * This function is expected to be called in master mode, which allows no
 	 * power saving. So we just check hw_init_completed.
 	 */
-
 	if (!padapter->hw_init_completed)
 		return -EPERM;
 
-	if (!wrqu->data.pointer)
-		return -EINVAL;
-
-	/*
-	 * Since we don't allocate memory for param in this function, we assume
-	 * the caller of this function will properly allocate and deallocate memory
-	 * for param.
-	 */
 	if (copy_from_user(param, wrqu->data.pointer, wrqu->data.length))
 		return -EFAULT;
 
@@ -3088,305 +3079,310 @@ static int get_private_handler_ieee_param(struct adapter *padapter,
 }
 
 static int rtw_hostapd_sta_flush_pvt(struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra)
+				     struct iw_request_info *info,
+				     union iwreq_data *wrqu,
+				     char *extra)
 {
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-
-	DBG_88E("%s\n", __func__);
-
-	flush_all_cam_entry(padapter); // Clear CAM.
-
+	flush_all_cam_entry(padapter); /* Clear CAM. */
 	return rtw_sta_flush(padapter);
 }
 
 static int rtw_add_sta_pvt(struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra)
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu,
+			   char *extra)
 {
-	int ret = 0;
-	struct sta_info *psta = NULL;
-	struct ieee_param *param = NULL;
+	int ret;
+	int flags;
+	struct sta_info *psta;
+	struct ieee_param *param;
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 
-	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
-
-	if (!param) {
-		DBG_88E(" rtw_add_sta: ieee_param allocate fail !!!\n");
-
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
 		return -ENOMEM;
-	}
 
 	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
 
-	if (ret != 0) {
-		kfree(param);
-		DBG_88E(" rtw_add_sta: ieee_param get fail !!!\n");
+	DBG_88E("rtw_add_sta(aid =%d) =%pM\n",
+		param->u.add_sta.aid,
+		(param->sta_addr));
 
-		return ret;
+	if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE))) {
+		ret = -EINVAL;
+		goto err_free_param;
 	}
 
-	DBG_88E("rtw_add_sta(aid =%d) =%pM\n", param->u.add_sta.aid, (param->sta_addr));
-
-	if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)))
-		return -EINVAL;
-
 	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
 	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
-	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
-	      return -EINVAL;
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
 
 	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
-	if (psta) {
-		int flags = param->u.add_sta.flags;
-		psta->aid = param->u.add_sta.aid; // aid = 1~2007.
-
-		memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
+	if (!psta) {
+		ret = -ENOMEM;
+		goto err_free_param;
+	}
 
-		// Check WMM cap.
-		if (WLAN_STA_WME&flags)
-			psta->qos_option = 1;
-		else
-			psta->qos_option = 0;
+	flags = param->u.add_sta.flags;
+	psta->aid = param->u.add_sta.aid; /* aid = 1~2007. */
 
-		if (pmlmepriv->qospriv.qos_option == 0)
-			psta->qos_option = 0;
+	memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
 
-		// Check 802.11n HT cap.
-		if (WLAN_STA_HT&flags) {
-			psta->htpriv.ht_option = true;
-			psta->qos_option = 1;
-			memcpy(&psta->htpriv.ht_cap,
-			       &param->u.add_sta.ht_cap,
-			       sizeof(struct ieee80211_ht_cap));
-		} else {
-			psta->htpriv.ht_option = false;
-		}
+	/* Check WMM cap. */
+	if (WLAN_STA_WME&flags)
+		psta->qos_option = 1;
+	else
+		psta->qos_option = 0;
 
-		if (pmlmepriv->htpriv.ht_option == false)
-			psta->htpriv.ht_option = false;
+	if (pmlmepriv->qospriv.qos_option == 0)
+		psta->qos_option = 0;
 
-		update_sta_info_apmode(padapter, psta);
+	/* Check 802.11n HT cap. */
+	if (WLAN_STA_HT&flags) {
+		psta->htpriv.ht_option = true;
+		psta->qos_option = 1;
+		memcpy(&psta->htpriv.ht_cap,
+		       &param->u.add_sta.ht_cap,
+		       sizeof(struct ieee80211_ht_cap));
 	} else {
-		ret = -ENOMEM;
+		psta->htpriv.ht_option = false;
 	}
 
-	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+	if (pmlmepriv->htpriv.ht_option == false)
+		psta->htpriv.ht_option = false;
+
+	update_sta_info_apmode(padapter, psta);
+
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
 		ret = -EFAULT;
 
-	return ret;
+	err_free_param:
+		kfree(param);
+		return ret;
 }
 
 static int rtw_del_sta_pvt(struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra)
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu,
+			   char *extra)
 {
-	int ret = 0;
-	struct sta_info *psta = NULL;
-	struct ieee_param *param = NULL;
+	int ret;
+	int updated;
+	struct sta_info *psta;
+	struct ieee_param *param;
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 	struct sta_priv *pstapriv = &padapter->stapriv;
-	int updated = 0;
-
-	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
-
-	if (!param) {
-		DBG_88E(" rtw_del_sta: ieee_param allocate fail !!!\n");
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
 		return -ENOMEM;
-	}
 
 	ret = get_private_handler_ieee_param(padapter, wrqu, param);
-
-	if (ret != 0) {
-		kfree(param);
-		DBG_88E(" rtw_del_sta: ieee_param get fail !!!\n");
-
-		return ret;
-	}
+	if (ret)
+		goto err_free_param;
 
 	DBG_88E("rtw_del_sta =%pM\n", (param->sta_addr));
 
-	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
-		return -EINVAL;
+	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
 
 	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
 	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
-	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
-	      return -EINVAL;
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
 
 	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
-	if (psta) {
-		spin_lock_bh(&pstapriv->asoc_list_lock);
-		if (!list_empty(&psta->asoc_list)) {
-			list_del_init(&psta->asoc_list);
-			pstapriv->asoc_list_cnt--;
-			updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
-		}
-		spin_unlock_bh(&pstapriv->asoc_list_lock);
-		associated_clients_update(padapter, updated);
-		psta = NULL;
-	} else {
+	if (!psta) {
 		DBG_88E("rtw_del_sta(), sta has already been removed or never been added\n");
+		ret = -ENOMEM;
+		goto err_free_param;
+	}
+
+	spin_lock_bh(&pstapriv->asoc_list_lock);
+
+	updated = 0;
+
+	if (!list_empty(&psta->asoc_list)) {
+		list_del_init(&psta->asoc_list);
+		pstapriv->asoc_list_cnt--;
+		updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
 	}
 
-	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+	spin_unlock_bh(&pstapriv->asoc_list_lock);
+	associated_clients_update(padapter, updated);
+
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
 		ret = -EFAULT;
 
-	return ret;
+	err_free_param:
+		kfree(param);
+		return ret;
 }
 
 static int rtw_set_beacon_pvt(struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra)
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu,
+			      char *extra)
 {
-	int ret = 0;
-	int len = 0;
-	unsigned char *pbuf = NULL;
-	struct ieee_param *param = NULL;
+	int ret;
+	int len;
+	unsigned char *pbuf;
+	struct ieee_param *param;
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 
-	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
-
-	if (!param) {
-		DBG_88E(" rtw_set_beacon: ieee_param allocate fail !!!\n");
-
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
 		return -ENOMEM;
-	}
 
 	ret = get_private_handler_ieee_param(padapter, wrqu, param);
-
-	if (ret != 0) {
-		kfree(param);
-		DBG_88E(" rtw_set_beacon: ieee_param get fail !!!\n");
-
-		return ret;
-	}
+	if (ret)
+		goto err_free_param;
 
 	len = wrqu->data.length;
 	pbuf = param->u.bcn_ie.buf;
 
 	DBG_88E("%s, len =%d\n", __func__, len);
 
-	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
-		return -EINVAL;
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
 
 	memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
 
 	if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
 		pstapriv->max_num_sta = NUM_STA;
 
-	if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) == _SUCCESS) //  12 = Param header, 2 = Not packed.
-		ret = 0;
-	else
+	if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) != _SUCCESS) { /*  12 = Param header, 2 = Not packed. */
 		ret = -EINVAL;
+		goto err_free_param;
+	}
 
-	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
 		ret = -EFAULT;
 
-	return ret;
+	err_free_param:
+		kfree(param);
+		return ret;
 }
 
 static int rtw_set_encryption_pvt(struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra)
+				  struct iw_request_info *info,
+				  union iwreq_data *wrqu,
+				  char *extra)
 {
-	int ret = 0;
-	int param_len = 0;
-	struct ieee_param *param = NULL;
-	u32 wep_key_idx, wep_key_len, wep_total_len;
-	struct ndis_802_11_wep	 *pwep = NULL;
-	struct sta_info *psta = NULL, *pbcmc_sta = NULL;
+	int ret;
+	int param_len;
+	u32 wep_key_idx;
+	u32 wep_key_len;
+	u32 wep_total_len;
+	struct sta_info *psta;
+	struct ieee_param *param;
+	struct sta_info *pbcmc_sta;
+	struct ndis_802_11_wep *pwep;
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
-	struct security_priv *psecuritypriv = &(padapter->securitypriv);
 	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct security_priv *psecuritypriv = &(padapter->securitypriv);
 
-	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
-
-	if (!param) {
-		ret = -ENOMEM;
-		DBG_88E(" r871x_set_encryption: ieee_param allocate fail !!!\n");
-
-		goto exit;
-	}
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
 
 	ret = get_private_handler_ieee_param(padapter, wrqu, param);
-
-	if (ret != 0) {
-		kfree(param);
-		DBG_88E(" r871x_set_encryption: ieee_param get fail !!!\n");
-
-		goto exit;
-	}
+	if (ret)
+		goto err_free_param;
 
 	param_len = wrqu->data.length;
-
-	DBG_88E("%s\n", __func__);
 	param->u.crypt.err = 0;
 	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
+
 	if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {
 		ret =  -EINVAL;
-		goto exit;
+		goto err_free_param;
 	}
+
+	psta = NULL;
+
 	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
 	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
 	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
 		if (param->u.crypt.idx >= WEP_KEYS) {
 			ret = -EINVAL;
-			goto exit;
+			goto err_free_param;
 		}
 	} else {
 		psta = rtw_get_stainfo(pstapriv, param->sta_addr);
 		if (!psta) {
 			DBG_88E("rtw_set_encryption(), sta has already been removed or never been added\n");
-			goto exit;
+			ret = -ENOMEM;
+			goto err_free_param;
 		}
 	}
 
 	if (strcmp(param->u.crypt.alg, "none") == 0 && (!psta)) {
-		// TODO: Clear default encryption keys.
-
-		DBG_88E("clear default encryption keys, keyid =%d\n", param->u.crypt.idx);
-		goto exit;
+		/* TODO: Clear default encryption keys. */
+		DBG_88E("clear default encryption keys, keyid =%d\n",
+			param->u.crypt.idx);
+		ret = -EINVAL;
+		goto err_free_param;
 	}
+
+	pwep = NULL;
+
 	if (strcmp(param->u.crypt.alg, "WEP") == 0 && (!psta)) {
 		DBG_88E("r871x_set_encryption, crypt.alg = WEP\n");
+
 		wep_key_idx = param->u.crypt.idx;
 		wep_key_len = param->u.crypt.key_len;
-		DBG_88E("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);
+
+		DBG_88E("r871x_set_encryption, wep_key_idx=%d, len=%d\n",
+			wep_key_idx,
+			wep_key_len);
+
 		if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
 			ret = -EINVAL;
-			goto exit;
+			goto err_free_param;
 		}
 
 		if (wep_key_len > 0) {
 			wep_key_len = wep_key_len <= 5 ? 5 : 13;
 			wep_total_len = wep_key_len + offsetof(struct ndis_802_11_wep, KeyMaterial);
-			pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len);
+
+			pwep = (struct ndis_802_11_wep *)kmalloc(wep_total_len, GFP_KERNEL);
 			if (!pwep) {
 				DBG_88E(" r871x_set_encryption: pwep allocate fail !!!\n");
-				goto exit;
+				ret = -ENOMEM;
+				goto err_free_param;
 			}
 
 			memset(pwep, 0, wep_total_len);
-
 			pwep->KeyLength = wep_key_len;
 			pwep->Length = wep_total_len;
 		}
 
 		pwep->KeyIndex = wep_key_idx;
-
 		memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
 
 		if (param->u.crypt.set_tx) {
@@ -3402,13 +3398,10 @@ static int rtw_set_encryption_pvt(struct net_device *dev,
 			}
 
 			psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
-
 			memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]),
 			       pwep->KeyMaterial,
 			       pwep->KeyLength);
-
 			psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
-
 			set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
 		} else {
 			DBG_88E("wep, set_tx = 0\n");
@@ -3422,16 +3415,19 @@ static int rtw_set_encryption_pvt(struct net_device *dev,
 			memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]),
 			       pwep->KeyMaterial,
 			       pwep->KeyLength);
-
 			psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
-
 			set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
 		}
 
-		goto exit;
+		ret = 0;
+
+		if (pwep)
+			goto err_free_pwep_param;
+		else
+			goto err_free_param;
 	}
 
-	if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { //  Group key.
+	if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /*  Group key. */
 		if (param->u.crypt.set_tx == 1) {
 			if (strcmp(param->u.crypt.alg, "WEP") == 0) {
 				DBG_88E("%s, set group_key, WEP\n", __func__);
@@ -3440,69 +3436,80 @@ static int rtw_set_encryption_pvt(struct net_device *dev,
 				       param->u.crypt.key,
 				       min_t(u16, param->u.crypt.key_len,
 				       16));
-
 				psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+
 				if (param->u.crypt.key_len == 13)
-						psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+					psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
 			} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
 				DBG_88E("%s, set group_key, TKIP\n", __func__);
+
 				psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
 				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
 				       param->u.crypt.key,
 				       min_t(u16, param->u.crypt.key_len,
 				       16));
-				// Set mic key.
+				/* Set mic key. */
 				memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey,
 				       &(param->u.crypt.key[16]),
 				       8);
 				memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey,
 				       &(param->u.crypt.key[24]),
 				       8);
-
 				psecuritypriv->busetkipkey = true;
 			} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
 				DBG_88E("%s, set group_key, CCMP\n", __func__);
+
 				psecuritypriv->dot118021XGrpPrivacy = _AES_;
 				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
 				       param->u.crypt.key,
 				       min_t(u16, param->u.crypt.key_len, 16));
 			} else {
 				DBG_88E("%s, set group_key, none\n", __func__);
+
 				psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
 			}
+
 			psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
 			psecuritypriv->binstallGrpkey = true;
 			psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;
 			set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
+
 			pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
 			if (pbcmc_sta) {
 				pbcmc_sta->ieee8021x_blocked = false;
-				pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; // rx will use bmc_sta's dot118021XPrivacy.
+				pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; /* rx will use bmc_sta's dot118021XPrivacy. */
 			}
 		}
-		goto exit;
+
+		ret = 0;
+
+		if (pwep)
+		        goto err_free_pwep_param;
+		else
+		        goto err_free_param;
 	}
 
-	if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { // psk/802_1x.
+	if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x. */
 		if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
 			if (param->u.crypt.set_tx == 1) {
-				memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
+				memcpy(psta->dot118021x_UncstKey.skey,
+				       param->u.crypt.key,
+				       min_t(u16, param->u.crypt.key_len, 16));
 
 				if (strcmp(param->u.crypt.alg, "WEP") == 0) {
 					DBG_88E("%s, set pairwise key, WEP\n", __func__);
 
 					psta->dot118021XPrivacy = _WEP40_;
+
 					if (param->u.crypt.key_len == 13)
 						psta->dot118021XPrivacy = _WEP104_;
 				} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
 					DBG_88E("%s, set pairwise key, TKIP\n", __func__);
 
 					psta->dot118021XPrivacy = _TKIP_;
-
-					// Set mic key.
+					/* Set mic key. */
 					memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
 					memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
-
 					psecuritypriv->busetkipkey = true;
 				} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
 					DBG_88E("%s, set pairwise key, CCMP\n", __func__);
@@ -3517,31 +3524,28 @@ static int rtw_set_encryption_pvt(struct net_device *dev,
 				set_pairwise_key(padapter, psta);
 
 				psta->ieee8021x_blocked = false;
-			} else { // Group key ?
+			} else { /* Group key ? */
 				if (strcmp(param->u.crypt.alg, "WEP") == 0) {
 					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
 					       param->u.crypt.key,
 					       min_t(u16, param->u.crypt.key_len, 16));
 					psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+
 					if (param->u.crypt.key_len == 13)
 						psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
 				} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
 					psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
-
 					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
 					       param->u.crypt.key,
 					       min_t(u16, param->u.crypt.key_len, 16));
-
-					// Set mic key.
+					/* Set mic key. */
 					memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey,
 					       &(param->u.crypt.key[16]), 8);
 					memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey,
 					       &(param->u.crypt.key[24]), 8);
-
 					psecuritypriv->busetkipkey = true;
 				} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
 					psecuritypriv->dot118021XGrpPrivacy = _AES_;
-
 					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
 					       param->u.crypt.key,
 					       min_t(u16, param->u.crypt.key_len, 16));
@@ -3552,553 +3556,569 @@ static int rtw_set_encryption_pvt(struct net_device *dev,
 				psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
 				psecuritypriv->binstallGrpkey = true;
 				psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;
-
 				set_group_key(padapter,
-					param->u.crypt.key,
-					psecuritypriv->dot118021XGrpPrivacy,
-					param->u.crypt.idx);
+					      param->u.crypt.key,
+					      psecuritypriv->dot118021XGrpPrivacy,
+					      param->u.crypt.idx);
 
 				pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
 				if (pbcmc_sta) {
 					pbcmc_sta->ieee8021x_blocked = false;
-					pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; // rx will use bmc_sta's dot118021XPrivacy.
+					pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; /* rx will use bmc_sta's dot118021XPrivacy. */
 				}
 			}
 		}
 	}
 
-exit:
-
-	kfree(pwep);
+	ret = 0;
 
-	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
 		ret = -EFAULT;
 
-	return ret;
+	if (pwep)
+		goto err_free_pwep_param;
+
+	err_free_param:
+		kfree(param);
+		return ret;
+
+	err_free_pwep_param:
+		kfree(pwep);
+		kfree(param);
+		return ret;
 }
 
 static int rtw_get_sta_wpaie_pvt(struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra)
+				 struct iw_request_info *info,
+				 union iwreq_data *wrqu,
+				 char *extra)
 {
-	int ret = 0;
-	struct sta_info *psta = NULL;
-	struct ieee_param *param = NULL;
+	int ret;
+	struct sta_info *psta;
+	struct ieee_param *param;
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 
-	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
-
-	if (!param) {
-		DBG_88E(" rtw_get_sta_wpaie: ieee_param allocate fail !!!\n");
-
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
 		return -ENOMEM;
-	}
 
 	ret = get_private_handler_ieee_param(padapter, wrqu, param);
-
-	if (ret != 0) {
-		kfree(param);
-		DBG_88E(" rtw_get_sta_wpaie: ieee_param get fail !!!\n");
-
-		return ret;
-	}
+	if (!ret)
+		goto err_free_param;
 
 	DBG_88E("rtw_get_sta_wpaie, sta_addr: %pM\n", (param->sta_addr));
 
-	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
-		return -EINVAL;
+	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
 
 	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
 	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
-	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
-	      return -EINVAL;
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
 
 	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
-	if (psta) {
-		if (psta->wpa_ie[0] == WLAN_EID_RSN ||
-		    psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
-		      int wpa_ie_len;
-		      int copy_len;
+	if (!psta) {
+		ret = -ENOMEM;
+		goto err_free_param;
+	}
 
-		      wpa_ie_len = psta->wpa_ie[1];
-		      copy_len = min_t(int, wpa_ie_len + 2, sizeof(psta->wpa_ie));
-		      param->u.wpa_ie.len = copy_len;
-		      memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
-		} else {
-			DBG_88E("sta's wpa_ie is NONE\n");
-		}
+	if (psta->wpa_ie[0] == WLAN_EID_RSN ||
+	    psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
+		int copy_len;
+		int wpa_ie_len;
+
+		wpa_ie_len = psta->wpa_ie[1];
+		copy_len = min_t(int, wpa_ie_len + 2, sizeof(psta->wpa_ie));
+		param->u.wpa_ie.len = copy_len;
+		memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
 	} else {
-		ret = -1;
+		DBG_88E("sta's wpa_ie is NONE\n");
 	}
 
-	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
 		ret = -EFAULT;
 
-	return ret;
+	err_free_param:
+		kfree(param);
+		return ret;
 }
 
 static int rtw_set_wps_beacon_pvt(struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra)
+				  struct iw_request_info *info,
+				  union iwreq_data *wrqu,
+				  char *extra)
 {
-	int ret = 0;
-	struct ieee_param *param = NULL;
+	int ret;
+	int len;
+	int ie_len;
+	struct ieee_param *param;
 	unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
-	int len, ie_len;
-
-	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
-
-	if (!param) {
-		DBG_88E(" rtw_set_wps_beacon: ieee_param allocate fail !!!\n");
+	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
 
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
 		return  -ENOMEM;
-	}
 
 	ret = get_private_handler_ieee_param(padapter, wrqu, param);
-
-	if (ret != 0) {
-		kfree(param);
-		DBG_88E(" rtw_set_wps_beacon: ieee_param get fail !!!\n");
-
-		return ret;
-	}
+	if (ret)
+		goto err_free_param;
 
 	len = wrqu->data.length;
 
 	DBG_88E("%s, len =%d\n", __func__, len);
 
-	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
-		return -EINVAL;
-
-	ie_len = len-12-2; // 12 = Param header, 2 = Not packed.
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
 
 	kfree(pmlmepriv->wps_beacon_ie);
 	pmlmepriv->wps_beacon_ie = NULL;
 
+	ie_len = len-12-2; /* 12 = Param header, 2 = Not packed. */
 	if (ie_len > 0) {
-		pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
-		pmlmepriv->wps_beacon_ie_len = ie_len;
+		pmlmepriv->wps_beacon_ie = kmalloc(ie_len, GFP_KERNEL);
 		if (!pmlmepriv->wps_beacon_ie) {
-			DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
-			return -EINVAL;
+			DBG_88E("%s()-%d: kmalloc() ERROR!\n", __func__, __LINE__);
+			ret = -EINVAL;
+			goto err_free_param;
 		}
 
+		pmlmepriv->wps_beacon_ie_len = ie_len;
 		memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
 		update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
-
 		pmlmeext->bstart_bss = true;
 	}
 
-	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
 		ret = -EFAULT;
 
-	return ret;
+	if (pmlmepriv->wps_beacon_ie)
+		goto err_free_param_wps_beacon_ie;
+
+	err_free_param:
+		kfree(param);
+		return ret;
+
+	err_free_param_wps_beacon_ie:
+		kfree(pmlmepriv->wps_beacon_ie);
+		kfree(param);
+		return ret;
+
 }
 
 static int rtw_set_wps_probe_resp_pvt(struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra)
+				      struct iw_request_info *info,
+				      union iwreq_data *wrqu,
+				      char *extra)
 {
-	int ret = 0;
-	struct ieee_param *param = NULL;
+	int ret;
+	int len;
+	int ie_len;
+	struct ieee_param *param;
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-	int len, ie_len;
-
-	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
-
-	if (!param) {
-		DBG_88E(" rtw_set_wps_probe_resp: ieee_param allocate fail !!!\n");
 
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
 		return -ENOMEM;
-	}
 
 	ret = get_private_handler_ieee_param(padapter, wrqu, param);
-
-	if (ret != 0) {
-		kfree(param);
-		DBG_88E(" rtw_set_wps_probe_resp: ieee_param get fail !!!\n");
-
-		return ret;
-	}
+	if (ret)
+		goto err_free_param;
 
 	len = wrqu->data.length;
 
 	DBG_88E("%s, len =%d\n", __func__, len);
 
-	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
-		return -EINVAL;
-
-	ie_len = len-12-2; // 12 = Param header, 2 = Not packed.
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
 
 	kfree(pmlmepriv->wps_probe_resp_ie);
 	pmlmepriv->wps_probe_resp_ie = NULL;
 
+	ie_len = len-12-2; /* 12 = Param header, 2 = Not packed. */
 	if (ie_len > 0) {
-		pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
-		pmlmepriv->wps_probe_resp_ie_len = ie_len;
+		pmlmepriv->wps_probe_resp_ie = kmalloc(ie_len, GFP_KERNEL);
 		if (!pmlmepriv->wps_probe_resp_ie) {
-			DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
-			return -EINVAL;
+			DBG_88E("%s()-%d: kmalloc() ERROR!\n", __func__, __LINE__);
+			ret = -EINVAL;
+			goto err_free_param;
 		}
+
+		pmlmepriv->wps_probe_resp_ie_len = ie_len;
 		memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
 	}
 
-	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
 		ret = -EFAULT;
 
-	return ret;
+	if (pmlmepriv->wps_probe_resp_ie)
+		goto err_free_param_wps_probe_resp_ie;
+
+	err_free_param:
+		kfree(param);
+		return ret;
+
+	err_free_param_wps_probe_resp_ie:
+		kfree(pmlmepriv->wps_probe_resp_ie);
+		kfree(param);
+		return ret;
 }
 
 static int rtw_set_wps_assoc_resp_pvt(struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra)
+				      struct iw_request_info *info,
+				      union iwreq_data *wrqu,
+				      char *extra)
 {
-	int ret = 0;
-	struct ieee_param *param = NULL;
+	int ret;
+	int len;
+	int ie_len;
+	struct ieee_param *param;
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-	int len, ie_len;
-
-	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
-
-	if (!param) {
-		DBG_88E(" rtw_set_wps_assoc_resp: ieee_param allocate fail !!!\n");
 
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
 		return -ENOMEM;
-	}
 
 	ret = get_private_handler_ieee_param(padapter, wrqu, param);
-
-	if (ret != 0) {
-		kfree(param);
-		DBG_88E(" rtw_set_wps_assoc_resp: ieee_param get fail !!!\n");
-
-		return ret;
-	}
+	if (ret)
+		goto err_free_param;
 
 	len = wrqu->data.length;
 
 	DBG_88E("%s, len =%d\n", __func__, len);
 
-	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
-		return -EINVAL;
-
-	ie_len = len-12-2; // 12 = Param header, 2 = Not packed.
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
 
 	kfree(pmlmepriv->wps_assoc_resp_ie);
 	pmlmepriv->wps_assoc_resp_ie = NULL;
 
+	ie_len = len-12-2; /* 12 = Param header, 2 = Not packed. */
 	if (ie_len > 0) {
-		pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
-		pmlmepriv->wps_assoc_resp_ie_len = ie_len;
+		pmlmepriv->wps_assoc_resp_ie = kmalloc(ie_len, GFP_KERNEL);
 		if (!pmlmepriv->wps_assoc_resp_ie) {
-			DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
-			return -EINVAL;
+			DBG_88E("%s()-%d: kmalloc() ERROR!\n", __func__, __LINE__);
+			ret = -EINVAL;
+			goto err_free_param;
 		}
 
+		pmlmepriv->wps_assoc_resp_ie_len = ie_len;
 		memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
 	}
 
-	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
 		ret = -EFAULT;
 
-	return ret;
+	if (pmlmepriv->wps_assoc_resp_ie)
+		goto err_free_param_wps_assoc_resp_ie;
+
+	err_free_param:
+		kfree(param);
+		return ret;
+
+	err_free_param_wps_assoc_resp_ie:
+		kfree(pmlmepriv->wps_assoc_resp_ie);
+		kfree(param);
+		return ret;
 }
 
 static int rtw_set_hidden_ssid_pvt(struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra)
+				   struct iw_request_info *info,
+				   union iwreq_data *wrqu,
+				   char *extra)
 {
-	int ret = 0;
-	struct ieee_param *param = NULL;
+	int ret;
+	u8 value;
+	struct ieee_param *param;
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
 	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
 
-	u8 value;
-
-	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
-
-	if (!param) {
-		DBG_88E(" rtw_set_hidden_ssid: ieee_param allocate fail !!!\n");
-
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
 		return -ENOMEM;
-	}
 
 	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
 
-	if (ret != 0) {
-		kfree(param);
-		DBG_88E(" rtw_set_hidden_ssid: ieee_param get fail !!!\n");
-
-		return ret;
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
 	}
 
-	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
-		return -EINVAL;
-
-	if (param->u.wpa_param.name != 0) // Dummy test.
+	if (param->u.wpa_param.name != 0) /* Dummy test. */
 		DBG_88E("%s name(%u) != 0\n", __func__, param->u.wpa_param.name);
+
 	value = param->u.wpa_param.value;
 
-	// Use the same definition of hostapd's ignore_broadcast_ssid.
+	/* Use the same definition of hostapd's ignore_broadcast_ssid. */
 	if (value != 1 && value != 2)
 		value = 0;
+
 	DBG_88E("%s value(%u)\n", __func__, value);
+
 	pmlmeinfo->hidden_ssid_mode = value;
 
-	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
 		ret = -EFAULT;
 
-	return ret;
+	err_free_param:
+		kfree(param);
+		return ret;
 }
 
 static int rtw_ioctl_get_sta_data_pvt(struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra)
+				      struct iw_request_info *info,
+				      union iwreq_data *wrqu,
+				      char *extra)
 {
-	int ret = 0;
-	struct sta_info *psta = NULL;
-	struct sta_data *psta_data = NULL;
-	struct ieee_param_ex *param_ex = NULL;
+	int ret;
+	struct sta_info *psta;
+	struct sta_data *psta_data;
+	struct ieee_param_ex *param_ex;
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 	struct sta_priv *pstapriv = &padapter->stapriv;
 
-	param_ex = (struct ieee_param_ex *)rtw_malloc(wrqu->data.length);
-
-	if (!param_ex) {
-		DBG_88E(" rtw_ioctl_get_sta_data: ieee_param_ex allocate fail !!!\n");
-
+	param_ex = (struct ieee_param_ex *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param_ex)
 		return -ENOMEM;
-	}
 
 	ret = get_private_handler_ieee_param(padapter, wrqu, param_ex);
-
-	if (ret != 0) {
-		kfree(param_ex);
-		DBG_88E(" rtw_ioctl_get_sta_data: ieee_param get fail !!!\n");
-
-		return ret;
-	}
+	if (ret)
+		goto err_free_param_ex;
 
 	psta_data = (struct sta_data *)param_ex->data;
 
 	DBG_88E("rtw_ioctl_get_sta_info, sta_addr: %pM\n", (param_ex->sta_addr));
 
-	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
-		return -EINVAL;
+	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) {
+		ret = -EINVAL;
+		goto err_free_param_ex;
+	}
 
 	if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
 	    param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
-	    param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff)
-	      return -EINVAL;
+	    param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff) {
+		ret = -EINVAL;
+		goto err_free_param_ex;
+	}
 
 	psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
-	if (psta) {
-		psta_data->aid = (u16)psta->aid;
-		psta_data->capability = psta->capability;
-		psta_data->flags = psta->flags;
+	if (!psta) {
+		ret = -ENOMEM;
+		goto err_free_param_ex;
+	}
 
-		/*
-		nonerp_set : BIT(0)
-		no_short_slot_time_set : BIT(1)
-		no_short_preamble_set : BIT(2)
-		no_ht_gf_set : BIT(3)
-		no_ht_set : BIT(4)
-		ht_20mhz_set : BIT(5)
-		*/
+	psta_data->aid = (u16)psta->aid;
+	psta_data->capability = psta->capability;
+	psta_data->flags = psta->flags;
 
-		psta_data->sta_set = \
-			((psta->nonerp_set) |
-			(psta->no_short_slot_time_set << 1) |
-			(psta->no_short_preamble_set << 2) |
-			(psta->no_ht_gf_set << 3) |
-			(psta->no_ht_set << 4) |
-			(psta->ht_20mhz_set << 5));
-		psta_data->tx_supp_rates_len =  psta->bssratelen;
-		memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
-		memcpy(&psta_data->ht_cap,
-		       &psta->htpriv.ht_cap,
-		       sizeof(struct ieee80211_ht_cap));
-		psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
-		psta_data->rx_bytes = psta->sta_stats.rx_bytes;
-		psta_data->rx_drops = psta->sta_stats.rx_drops;
-		psta_data->tx_pkts = psta->sta_stats.tx_pkts;
-		psta_data->tx_bytes = psta->sta_stats.tx_bytes;
-		psta_data->tx_drops = psta->sta_stats.tx_drops;
-	} else {
-		ret = -1;
-	}
+	/*
+	nonerp_set : BIT(0)
+	no_short_slot_time_set : BIT(1)
+	no_short_preamble_set : BIT(2)
+	no_ht_gf_set : BIT(3)
+	no_ht_set : BIT(4)
+	ht_20mhz_set : BIT(5)
+	*/
 
-	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param_ex, wrqu->data.length)))
+	psta_data->sta_set = \
+		((psta->nonerp_set) |
+		(psta->no_short_slot_time_set << 1) |
+		(psta->no_short_preamble_set << 2) |
+		(psta->no_ht_gf_set << 3) |
+		(psta->no_ht_set << 4) |
+		(psta->ht_20mhz_set << 5));
+	psta_data->tx_supp_rates_len =  psta->bssratelen;
+	memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
+	memcpy(&psta_data->ht_cap,
+	       &psta->htpriv.ht_cap,
+	       sizeof(struct ieee80211_ht_cap));
+	psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
+	psta_data->rx_bytes = psta->sta_stats.rx_bytes;
+	psta_data->rx_drops = psta->sta_stats.rx_drops;
+	psta_data->tx_pkts = psta->sta_stats.tx_pkts;
+	psta_data->tx_bytes = psta->sta_stats.tx_bytes;
+	psta_data->tx_drops = psta->sta_stats.tx_drops;
+
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param_ex, wrqu->data.length))
 		ret = -EFAULT;
 
-	return ret;
+	err_free_param_ex:
+		kfree(param_ex);
+		return ret;
 }
 
 static int rtw_ioctl_set_macaddr_acl_pvt(struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra)
+					 struct iw_request_info *info,
+					 union iwreq_data *wrqu,
+					 char *extra)
 {
-	int ret = 0;
-	struct ieee_param *param = NULL;
+	int ret;
+	struct ieee_param *param;
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 
-	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
-
-	if (!param) {
-		DBG_88E(" rtw_ioctl_set_macaddr_acl: ieee_param allocate fail !!!\n");
-
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
 		return -ENOMEM;
-	}
 
 	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
 
-	if (ret != 0) {
-		kfree(param);
-		DBG_88E(" rtw_ioctl_set_macaddr_acl: ieee_param get fail !!!\n");
-
-		return ret;
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
 	}
 
-	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
-		return -EINVAL;
-
 	rtw_set_macaddr_acl(padapter, param->u.mlme.command);
 
-	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
 		ret = -EFAULT;
 
-	return ret;
+	err_free_param:
+		kfree(param);
+		return ret;
 }
 
 static int rtw_ioctl_acl_add_sta_pvt(struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra)
+				     struct iw_request_info *info,
+				     union iwreq_data *wrqu,
+				     char *extra)
 {
-	int ret = 0;
-	struct ieee_param *param = NULL;
+	int ret;
+	struct ieee_param *param;
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 
-	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
-
-	if (!param) {
-		DBG_88E(" rtw_ioctl_acl_add_sta: ieee_param allocate fail !!!\n");
-
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
 		return -ENOMEM;
-	}
 
 	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
 
-	if (ret != 0) {
-		kfree(param);
-		DBG_88E(" rtw_ioctl_acl_add_sta: ieee_param get fail !!!\n");
-
-		return ret;
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
 	}
 
-	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
-		return -EINVAL;
-
 	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
 	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
-	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
-	      return -EINVAL;
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
 
 	ret = rtw_acl_add_sta(padapter, param->sta_addr);
 
-	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
 		ret = -EFAULT;
 
-	return ret;
+	err_free_param:
+		kfree(param);
+		return ret;
 }
 
 static int rtw_ioctl_acl_remove_sta_pvt(struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra)
+					struct iw_request_info *info,
+					union iwreq_data *wrqu,
+					char *extra)
 {
-	int ret = 0;
-	struct ieee_param *param = NULL;
+	int ret;
+	struct ieee_param *param;
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 
-	param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
-
-	if (!param) {
-		DBG_88E(" rtw_ioctl_acl_remove_sta: ieee_param allocate fail !!!\n");
-
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
 		return -ENOMEM;
-	}
 
 	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
 
-	if (ret != 0) {
-		kfree(param);
-		DBG_88E(" rtw_ioctl_acl_remove_sta: ieee_param get fail !!!\n");
-
-		return ret;
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
 	}
 
-	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
-		return -EINVAL;
-
 	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
 	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
-	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
-	      return -EINVAL;
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
 
 	ret = rtw_acl_remove_sta(padapter, param->sta_addr);
 
-	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
 		ret = -EFAULT;
 
-	return ret;
+	err_free_param:
+		kfree(param);
+		return ret;
 }
 
 static iw_handler rtw_handlers_private[] = {
-	NULL,                          // Empty
-	rtw_hostapd_sta_flush_pvt,     // RTL871X_HOSTAPD_FLUSH
-	rtw_add_sta_pvt,               // RTL871X_HOSTAPD_ADD_STA
-	rtw_del_sta_pvt,               // RTL871X_HOSTAPD_REMOVE_STA
-	rtw_ioctl_get_sta_data_pvt,    // RTL871X_HOSTAPD_GET_INFO_STA
-	rtw_get_sta_wpaie_pvt,         // RTL871X_HOSTAPD_GET_WPAIE_STA
-	rtw_set_encryption_pvt,        // RTL871X_SET_ENCRYPTION
-	NULL,                          // RTL871X_GET_ENCRYPTION
-	NULL,                          // RTL871X_HOSTAPD_SET_FLAGS_STA
-	NULL,                          // RTL871X_HOSTAPD_GET_RID
-	NULL,                          // RTL871X_HOSTAPD_SET_RID
-	NULL,                          // RTL871X_HOSTAPD_SET_ASSOC_AP_ADDR
-	NULL,                          // RTL871X_HOSTAPD_SET_GENERIC_ELEMENT
-	NULL,                          // RTL871X_HOSTAPD_MLME
-	NULL,                          // RTL871X_HOSTAPD_SCAN_REQ
-	NULL,                          // RTL871X_HOSTAPD_STA_CLEAR_STATS
-	rtw_set_beacon_pvt,            // RTL871X_HOSTAPD_SET_BEACON
-	rtw_set_wps_beacon_pvt,        // RTL871X_HOSTAPD_SET_WPS_BEACON
-	rtw_set_wps_probe_resp_pvt,    // RTL871X_HOSTAPD_SET_WPS_PROBE_RESP
-	rtw_set_wps_assoc_resp_pvt,    // RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP
-	rtw_set_hidden_ssid_pvt,       // RTL871X_HOSTAPD_SET_HIDDEN_SSID
-	rtw_ioctl_set_macaddr_acl_pvt, // RTL871X_HOSTAPD_SET_MACADDR_ACL
-	rtw_ioctl_acl_add_sta_pvt,     // RTL871X_HOSTAPD_ACL_ADD_STA
-	rtw_ioctl_acl_remove_sta_pvt,  // RTL871X_HOSTAPD_ACL_REMOVE_STA
+	NULL,                          /* Empty */
+	rtw_hostapd_sta_flush_pvt,     /* RTL871X_HOSTAPD_FLUSH */
+	rtw_add_sta_pvt,               /* RTL871X_HOSTAPD_ADD_STA */
+	rtw_del_sta_pvt,               /* RTL871X_HOSTAPD_REMOVE_STA */
+	rtw_ioctl_get_sta_data_pvt,    /* RTL871X_HOSTAPD_GET_INFO_STA */
+	rtw_get_sta_wpaie_pvt,         /* RTL871X_HOSTAPD_GET_WPAIE_STA */
+	rtw_set_encryption_pvt,        /* RTL871X_SET_ENCRYPTION */
+	NULL,                          /* RTL871X_GET_ENCRYPTION */
+	NULL,                          /* RTL871X_HOSTAPD_SET_FLAGS_STA */
+	NULL,                          /* RTL871X_HOSTAPD_GET_RID */
+	NULL,                          /* RTL871X_HOSTAPD_SET_RID */
+	NULL,                          /* RTL871X_HOSTAPD_SET_ASSOC_AP_ADDR */
+	NULL,                          /* RTL871X_HOSTAPD_SET_GENERIC_ELEMENT */
+	NULL,                          /* RTL871X_HOSTAPD_MLME */
+	NULL,                          /* RTL871X_HOSTAPD_SCAN_REQ */
+	NULL,                          /* RTL871X_HOSTAPD_STA_CLEAR_STATS */
+	rtw_set_beacon_pvt,            /* RTL871X_HOSTAPD_SET_BEACON */
+	rtw_set_wps_beacon_pvt,        /* RTL871X_HOSTAPD_SET_WPS_BEACON */
+	rtw_set_wps_probe_resp_pvt,    /* RTL871X_HOSTAPD_SET_WPS_PROBE_RESP */
+	rtw_set_wps_assoc_resp_pvt,    /* RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP */
+	rtw_set_hidden_ssid_pvt,       /* RTL871X_HOSTAPD_SET_HIDDEN_SSID */
+	rtw_ioctl_set_macaddr_acl_pvt, /* RTL871X_HOSTAPD_SET_MACADDR_ACL */
+	rtw_ioctl_acl_add_sta_pvt,     /* RTL871X_HOSTAPD_ACL_ADD_STA */
+	rtw_ioctl_acl_remove_sta_pvt,  /* RTL871X_HOSTAPD_ACL_REMOVE_STA */
 };
 
 static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2] staging: rtl8188eu: Fix private WEXT IOCTL calls
  2017-11-23  1:29 [PATCH] staging: rtl8188eu: Fix private WEXT IOCTL calls ishraq.i.ashraf
  2017-11-23 13:24 ` Dan Carpenter
  2017-11-25  0:52 ` [PATCH 2/2] " ishraq.i.ashraf
@ 2017-11-25  1:29 ` ishraq.i.ashraf
  2017-11-25  4:55   ` Dan Carpenter
  2017-11-25 18:29 ` [PATCH v3] " ishraq.i.ashraf
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: ishraq.i.ashraf @ 2017-11-25  1:29 UTC (permalink / raw)
  To: gregkh
  Cc: himanshujha199640, goudapatilk, insafonov, dan.carpenter, devel,
	linux-kernel, Ishraq Ibne Ashraf

From: Ishraq Ibne Ashraf <ishraq.i.ashraf@gmail.com>

Commit 8bfb36766064 ("wireless: wext: remove ndo_do_ioctl fallback") breaks private WEXT
IOCTL calls of this driver as these are not invoked through ndo_do_ioctl
interface anymore. As a result hostapd stops working with this driver. In
this patch this problem is solved by implementing equivalent private IOCTL
functions of the existing ones which are accessed via iw_handler_def
interface.

Signed-off-by: Ishraq Ibne Ashraf <ishraq.i.ashraf@gmail.com>
---
 drivers/staging/rtl8188eu/os_dep/ioctl_linux.c | 1062 ++++++++++++++++++++++++
 1 file changed, 1062 insertions(+)

diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
index c0664dc..e871344 100644
--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
@@ -3061,6 +3061,1066 @@ static iw_handler rtw_handlers[] = {
 	NULL,					/*---hole---*/
 };
 
+static int get_private_handler_ieee_param(struct adapter *padapter,
+					  union iwreq_data *wrqu,
+					  void *param)
+{
+	/*
+	 * This function is expected to be called in master mode, which allows no
+	 * power saving. So we just check hw_init_completed.
+	 */
+	if (!padapter->hw_init_completed)
+		return -EPERM;
+
+	if (copy_from_user(param, wrqu->data.pointer, wrqu->data.length))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int rtw_hostapd_sta_flush_pvt(struct net_device *dev,
+				     struct iw_request_info *info,
+				     union iwreq_data *wrqu,
+				     char *extra)
+{
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	flush_all_cam_entry(padapter); /* Clear CAM. */
+	return rtw_sta_flush(padapter);
+}
+
+static int rtw_add_sta_pvt(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu,
+			   char *extra)
+{
+	int ret;
+	int flags;
+	struct sta_info *psta;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	DBG_88E("rtw_add_sta(aid =%d) =%pM\n",
+		param->u.add_sta.aid,
+		(param->sta_addr));
+
+	if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE))) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+	if (!psta) {
+		ret = -ENOMEM;
+		goto err_free_param;
+	}
+
+	flags = param->u.add_sta.flags;
+	psta->aid = param->u.add_sta.aid; /* aid = 1~2007. */
+
+	memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
+
+	/* Check WMM cap. */
+	if (WLAN_STA_WME&flags)
+		psta->qos_option = 1;
+	else
+		psta->qos_option = 0;
+
+	if (pmlmepriv->qospriv.qos_option == 0)
+		psta->qos_option = 0;
+
+	/* Check 802.11n HT cap. */
+	if (WLAN_STA_HT&flags) {
+		psta->htpriv.ht_option = true;
+		psta->qos_option = 1;
+		memcpy(&psta->htpriv.ht_cap,
+		       &param->u.add_sta.ht_cap,
+		       sizeof(struct ieee80211_ht_cap));
+	} else {
+		psta->htpriv.ht_option = false;
+	}
+
+	if (pmlmepriv->htpriv.ht_option == false)
+		psta->htpriv.ht_option = false;
+
+	update_sta_info_apmode(padapter, psta);
+
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
+		ret = -EFAULT;
+
+	err_free_param:
+		kfree(param);
+		return ret;
+}
+
+static int rtw_del_sta_pvt(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu,
+			   char *extra)
+{
+	int ret;
+	int updated;
+	struct sta_info *psta;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	DBG_88E("rtw_del_sta =%pM\n", (param->sta_addr));
+
+	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+	if (!psta) {
+		DBG_88E("rtw_del_sta(), sta has already been removed or never been added\n");
+		ret = -ENOMEM;
+		goto err_free_param;
+	}
+
+	spin_lock_bh(&pstapriv->asoc_list_lock);
+
+	updated = 0;
+
+	if (!list_empty(&psta->asoc_list)) {
+		list_del_init(&psta->asoc_list);
+		pstapriv->asoc_list_cnt--;
+		updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
+	}
+
+	spin_unlock_bh(&pstapriv->asoc_list_lock);
+	associated_clients_update(padapter, updated);
+
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
+		ret = -EFAULT;
+
+	err_free_param:
+		kfree(param);
+		return ret;
+}
+
+static int rtw_set_beacon_pvt(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu,
+			      char *extra)
+{
+	int ret;
+	int len;
+	unsigned char *pbuf;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	len = wrqu->data.length;
+	pbuf = param->u.bcn_ie.buf;
+
+	DBG_88E("%s, len =%d\n", __func__, len);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
+
+	if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
+		pstapriv->max_num_sta = NUM_STA;
+
+	if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) != _SUCCESS) { /*  12 = Param header, 2 = Not packed. */
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
+		ret = -EFAULT;
+
+	err_free_param:
+		kfree(param);
+		return ret;
+}
+
+static int rtw_set_encryption_pvt(struct net_device *dev,
+				  struct iw_request_info *info,
+				  union iwreq_data *wrqu,
+				  char *extra)
+{
+	int ret;
+	int param_len;
+	u32 wep_key_idx;
+	u32 wep_key_len;
+	u32 wep_total_len;
+	struct sta_info *psta;
+	struct ieee_param *param;
+	struct sta_info *pbcmc_sta;
+	struct ndis_802_11_wep *pwep;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct security_priv *psecuritypriv = &(padapter->securitypriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	param_len = wrqu->data.length;
+	param->u.crypt.err = 0;
+	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
+
+	if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {
+		ret =  -EINVAL;
+		goto err_free_param;
+	}
+
+	psta = NULL;
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		if (param->u.crypt.idx >= WEP_KEYS) {
+			ret = -EINVAL;
+			goto err_free_param;
+		}
+	} else {
+		psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+		if (!psta) {
+			DBG_88E("rtw_set_encryption(), sta has already been removed or never been added\n");
+			ret = -ENOMEM;
+			goto err_free_param;
+		}
+	}
+
+	if (strcmp(param->u.crypt.alg, "none") == 0 && (!psta)) {
+		/* TODO: Clear default encryption keys. */
+		DBG_88E("clear default encryption keys, keyid =%d\n",
+			param->u.crypt.idx);
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	pwep = NULL;
+
+	if (strcmp(param->u.crypt.alg, "WEP") == 0 && (!psta)) {
+		DBG_88E("r871x_set_encryption, crypt.alg = WEP\n");
+
+		wep_key_idx = param->u.crypt.idx;
+		wep_key_len = param->u.crypt.key_len;
+
+		DBG_88E("r871x_set_encryption, wep_key_idx=%d, len=%d\n",
+			wep_key_idx,
+			wep_key_len);
+
+		if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
+			ret = -EINVAL;
+			goto err_free_param;
+		}
+
+		if (wep_key_len > 0) {
+			wep_key_len = wep_key_len <= 5 ? 5 : 13;
+			wep_total_len = wep_key_len + offsetof(struct ndis_802_11_wep, KeyMaterial);
+
+			pwep = (struct ndis_802_11_wep *)kmalloc(wep_total_len, GFP_KERNEL);
+			if (!pwep) {
+				DBG_88E(" r871x_set_encryption: pwep allocate fail !!!\n");
+				ret = -ENOMEM;
+				goto err_free_param;
+			}
+
+			memset(pwep, 0, wep_total_len);
+			pwep->KeyLength = wep_key_len;
+			pwep->Length = wep_total_len;
+		}
+
+		pwep->KeyIndex = wep_key_idx;
+		memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
+
+		if (param->u.crypt.set_tx) {
+			DBG_88E("wep, set_tx = 1\n");
+
+			psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
+			psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
+			psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+
+			if (pwep->KeyLength == 13) {
+				psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
+				psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+			}
+
+			psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
+			memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]),
+			       pwep->KeyMaterial,
+			       pwep->KeyLength);
+			psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
+			set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
+		} else {
+			DBG_88E("wep, set_tx = 0\n");
+
+			/*
+			 * Don't update "psecuritypriv->dot11PrivacyAlgrthm" and
+			 * "psecuritypriv->dot11PrivacyKeyIndex = keyid", but rtw_set_key()
+			 * can to cam.
+			 */
+
+			memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]),
+			       pwep->KeyMaterial,
+			       pwep->KeyLength);
+			psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
+			set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
+		}
+
+		ret = 0;
+
+		if (pwep)
+			goto err_free_pwep_param;
+		else
+			goto err_free_param;
+	}
+
+	if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /*  Group key. */
+		if (param->u.crypt.set_tx == 1) {
+			if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+				DBG_88E("%s, set group_key, WEP\n", __func__);
+
+				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+				       param->u.crypt.key,
+				       min_t(u16, param->u.crypt.key_len,
+				       16));
+				psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+
+				if (param->u.crypt.key_len == 13)
+					psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+			} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+				DBG_88E("%s, set group_key, TKIP\n", __func__);
+
+				psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
+				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+				       param->u.crypt.key,
+				       min_t(u16, param->u.crypt.key_len,
+				       16));
+				/* Set mic key. */
+				memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey,
+				       &(param->u.crypt.key[16]),
+				       8);
+				memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey,
+				       &(param->u.crypt.key[24]),
+				       8);
+				psecuritypriv->busetkipkey = true;
+			} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+				DBG_88E("%s, set group_key, CCMP\n", __func__);
+
+				psecuritypriv->dot118021XGrpPrivacy = _AES_;
+				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+				       param->u.crypt.key,
+				       min_t(u16, param->u.crypt.key_len, 16));
+			} else {
+				DBG_88E("%s, set group_key, none\n", __func__);
+
+				psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+			}
+
+			psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
+			psecuritypriv->binstallGrpkey = true;
+			psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;
+			set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
+
+			pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+			if (pbcmc_sta) {
+				pbcmc_sta->ieee8021x_blocked = false;
+				pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; /* rx will use bmc_sta's dot118021XPrivacy. */
+			}
+		}
+
+		ret = 0;
+
+		if (pwep)
+		        goto err_free_pwep_param;
+		else
+		        goto err_free_param;
+	}
+
+	if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x. */
+		if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+			if (param->u.crypt.set_tx == 1) {
+				memcpy(psta->dot118021x_UncstKey.skey,
+				       param->u.crypt.key,
+				       min_t(u16, param->u.crypt.key_len, 16));
+
+				if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+					DBG_88E("%s, set pairwise key, WEP\n", __func__);
+
+					psta->dot118021XPrivacy = _WEP40_;
+
+					if (param->u.crypt.key_len == 13)
+						psta->dot118021XPrivacy = _WEP104_;
+				} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+					DBG_88E("%s, set pairwise key, TKIP\n", __func__);
+
+					psta->dot118021XPrivacy = _TKIP_;
+					/* Set mic key. */
+					memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
+					memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
+					psecuritypriv->busetkipkey = true;
+				} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+					DBG_88E("%s, set pairwise key, CCMP\n", __func__);
+
+					psta->dot118021XPrivacy = _AES_;
+				} else {
+					DBG_88E("%s, set pairwise key, none\n", __func__);
+
+					psta->dot118021XPrivacy = _NO_PRIVACY_;
+				}
+
+				set_pairwise_key(padapter, psta);
+
+				psta->ieee8021x_blocked = false;
+			} else { /* Group key ? */
+				if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+					       param->u.crypt.key,
+					       min_t(u16, param->u.crypt.key_len, 16));
+					psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+
+					if (param->u.crypt.key_len == 13)
+						psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+				} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+					psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
+					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+					       param->u.crypt.key,
+					       min_t(u16, param->u.crypt.key_len, 16));
+					/* Set mic key. */
+					memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey,
+					       &(param->u.crypt.key[16]), 8);
+					memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey,
+					       &(param->u.crypt.key[24]), 8);
+					psecuritypriv->busetkipkey = true;
+				} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+					psecuritypriv->dot118021XGrpPrivacy = _AES_;
+					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+					       param->u.crypt.key,
+					       min_t(u16, param->u.crypt.key_len, 16));
+				} else {
+					psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+				}
+
+				psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
+				psecuritypriv->binstallGrpkey = true;
+				psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;
+				set_group_key(padapter,
+					      param->u.crypt.key,
+					      psecuritypriv->dot118021XGrpPrivacy,
+					      param->u.crypt.idx);
+
+				pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+				if (pbcmc_sta) {
+					pbcmc_sta->ieee8021x_blocked = false;
+					pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; /* rx will use bmc_sta's dot118021XPrivacy. */
+				}
+			}
+		}
+	}
+
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
+		ret = -EFAULT;
+
+	if (pwep)
+		goto err_free_pwep_param;
+
+	err_free_param:
+		kfree(param);
+		return ret;
+
+	err_free_pwep_param:
+		kfree(pwep);
+		kfree(param);
+		return ret;
+}
+
+static int rtw_get_sta_wpaie_pvt(struct net_device *dev,
+				 struct iw_request_info *info,
+				 union iwreq_data *wrqu,
+				 char *extra)
+{
+	int ret;
+	struct sta_info *psta;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (!ret)
+		goto err_free_param;
+
+	DBG_88E("rtw_get_sta_wpaie, sta_addr: %pM\n", (param->sta_addr));
+
+	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+	if (!psta) {
+		ret = -ENOMEM;
+		goto err_free_param;
+	}
+
+	if (psta->wpa_ie[0] == WLAN_EID_RSN ||
+	    psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
+		int copy_len;
+		int wpa_ie_len;
+
+		wpa_ie_len = psta->wpa_ie[1];
+		copy_len = min_t(int, wpa_ie_len + 2, sizeof(psta->wpa_ie));
+		param->u.wpa_ie.len = copy_len;
+		memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
+	} else {
+		DBG_88E("sta's wpa_ie is NONE\n");
+	}
+
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
+		ret = -EFAULT;
+
+	err_free_param:
+		kfree(param);
+		return ret;
+}
+
+static int rtw_set_wps_beacon_pvt(struct net_device *dev,
+				  struct iw_request_info *info,
+				  union iwreq_data *wrqu,
+				  char *extra)
+{
+	int ret;
+	int len;
+	int ie_len;
+	struct ieee_param *param;
+	unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return  -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	len = wrqu->data.length;
+
+	DBG_88E("%s, len =%d\n", __func__, len);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	kfree(pmlmepriv->wps_beacon_ie);
+	pmlmepriv->wps_beacon_ie = NULL;
+
+	ie_len = len-12-2; /* 12 = Param header, 2 = Not packed. */
+	if (ie_len > 0) {
+		pmlmepriv->wps_beacon_ie = kmalloc(ie_len, GFP_KERNEL);
+		if (!pmlmepriv->wps_beacon_ie) {
+			DBG_88E("%s()-%d: kmalloc() ERROR!\n", __func__, __LINE__);
+			ret = -EINVAL;
+			goto err_free_param;
+		}
+
+		pmlmepriv->wps_beacon_ie_len = ie_len;
+		memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
+		update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
+		pmlmeext->bstart_bss = true;
+	}
+
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
+		ret = -EFAULT;
+
+	if (pmlmepriv->wps_beacon_ie)
+		goto err_free_param_wps_beacon_ie;
+
+	err_free_param:
+		kfree(param);
+		return ret;
+
+	err_free_param_wps_beacon_ie:
+		kfree(pmlmepriv->wps_beacon_ie);
+		kfree(param);
+		return ret;
+
+}
+
+static int rtw_set_wps_probe_resp_pvt(struct net_device *dev,
+				      struct iw_request_info *info,
+				      union iwreq_data *wrqu,
+				      char *extra)
+{
+	int ret;
+	int len;
+	int ie_len;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	len = wrqu->data.length;
+
+	DBG_88E("%s, len =%d\n", __func__, len);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	kfree(pmlmepriv->wps_probe_resp_ie);
+	pmlmepriv->wps_probe_resp_ie = NULL;
+
+	ie_len = len-12-2; /* 12 = Param header, 2 = Not packed. */
+	if (ie_len > 0) {
+		pmlmepriv->wps_probe_resp_ie = kmalloc(ie_len, GFP_KERNEL);
+		if (!pmlmepriv->wps_probe_resp_ie) {
+			DBG_88E("%s()-%d: kmalloc() ERROR!\n", __func__, __LINE__);
+			ret = -EINVAL;
+			goto err_free_param;
+		}
+
+		pmlmepriv->wps_probe_resp_ie_len = ie_len;
+		memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
+	}
+
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
+		ret = -EFAULT;
+
+	if (pmlmepriv->wps_probe_resp_ie)
+		goto err_free_param_wps_probe_resp_ie;
+
+	err_free_param:
+		kfree(param);
+		return ret;
+
+	err_free_param_wps_probe_resp_ie:
+		kfree(pmlmepriv->wps_probe_resp_ie);
+		kfree(param);
+		return ret;
+}
+
+static int rtw_set_wps_assoc_resp_pvt(struct net_device *dev,
+				      struct iw_request_info *info,
+				      union iwreq_data *wrqu,
+				      char *extra)
+{
+	int ret;
+	int len;
+	int ie_len;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	len = wrqu->data.length;
+
+	DBG_88E("%s, len =%d\n", __func__, len);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	kfree(pmlmepriv->wps_assoc_resp_ie);
+	pmlmepriv->wps_assoc_resp_ie = NULL;
+
+	ie_len = len-12-2; /* 12 = Param header, 2 = Not packed. */
+	if (ie_len > 0) {
+		pmlmepriv->wps_assoc_resp_ie = kmalloc(ie_len, GFP_KERNEL);
+		if (!pmlmepriv->wps_assoc_resp_ie) {
+			DBG_88E("%s()-%d: kmalloc() ERROR!\n", __func__, __LINE__);
+			ret = -EINVAL;
+			goto err_free_param;
+		}
+
+		pmlmepriv->wps_assoc_resp_ie_len = ie_len;
+		memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
+	}
+
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
+		ret = -EFAULT;
+
+	if (pmlmepriv->wps_assoc_resp_ie)
+		goto err_free_param_wps_assoc_resp_ie;
+
+	err_free_param:
+		kfree(param);
+		return ret;
+
+	err_free_param_wps_assoc_resp_ie:
+		kfree(pmlmepriv->wps_assoc_resp_ie);
+		kfree(param);
+		return ret;
+}
+
+static int rtw_set_hidden_ssid_pvt(struct net_device *dev,
+				   struct iw_request_info *info,
+				   union iwreq_data *wrqu,
+				   char *extra)
+{
+	int ret;
+	u8 value;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	if (param->u.wpa_param.name != 0) /* Dummy test. */
+		DBG_88E("%s name(%u) != 0\n", __func__, param->u.wpa_param.name);
+
+	value = param->u.wpa_param.value;
+
+	/* Use the same definition of hostapd's ignore_broadcast_ssid. */
+	if (value != 1 && value != 2)
+		value = 0;
+
+	DBG_88E("%s value(%u)\n", __func__, value);
+
+	pmlmeinfo->hidden_ssid_mode = value;
+
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
+		ret = -EFAULT;
+
+	err_free_param:
+		kfree(param);
+		return ret;
+}
+
+static int rtw_ioctl_get_sta_data_pvt(struct net_device *dev,
+				      struct iw_request_info *info,
+				      union iwreq_data *wrqu,
+				      char *extra)
+{
+	int ret;
+	struct sta_info *psta;
+	struct sta_data *psta_data;
+	struct ieee_param_ex *param_ex;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	param_ex = (struct ieee_param_ex *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param_ex)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param_ex);
+	if (ret)
+		goto err_free_param_ex;
+
+	psta_data = (struct sta_data *)param_ex->data;
+
+	DBG_88E("rtw_ioctl_get_sta_info, sta_addr: %pM\n", (param_ex->sta_addr));
+
+	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) {
+		ret = -EINVAL;
+		goto err_free_param_ex;
+	}
+
+	if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
+	    param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
+	    param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff) {
+		ret = -EINVAL;
+		goto err_free_param_ex;
+	}
+
+	psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
+	if (!psta) {
+		ret = -ENOMEM;
+		goto err_free_param_ex;
+	}
+
+	psta_data->aid = (u16)psta->aid;
+	psta_data->capability = psta->capability;
+	psta_data->flags = psta->flags;
+
+	/*
+	nonerp_set : BIT(0)
+	no_short_slot_time_set : BIT(1)
+	no_short_preamble_set : BIT(2)
+	no_ht_gf_set : BIT(3)
+	no_ht_set : BIT(4)
+	ht_20mhz_set : BIT(5)
+	*/
+
+	psta_data->sta_set = \
+		((psta->nonerp_set) |
+		(psta->no_short_slot_time_set << 1) |
+		(psta->no_short_preamble_set << 2) |
+		(psta->no_ht_gf_set << 3) |
+		(psta->no_ht_set << 4) |
+		(psta->ht_20mhz_set << 5));
+	psta_data->tx_supp_rates_len =  psta->bssratelen;
+	memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
+	memcpy(&psta_data->ht_cap,
+	       &psta->htpriv.ht_cap,
+	       sizeof(struct ieee80211_ht_cap));
+	psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
+	psta_data->rx_bytes = psta->sta_stats.rx_bytes;
+	psta_data->rx_drops = psta->sta_stats.rx_drops;
+	psta_data->tx_pkts = psta->sta_stats.tx_pkts;
+	psta_data->tx_bytes = psta->sta_stats.tx_bytes;
+	psta_data->tx_drops = psta->sta_stats.tx_drops;
+
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param_ex, wrqu->data.length))
+		ret = -EFAULT;
+
+	err_free_param_ex:
+		kfree(param_ex);
+		return ret;
+}
+
+static int rtw_ioctl_set_macaddr_acl_pvt(struct net_device *dev,
+					 struct iw_request_info *info,
+					 union iwreq_data *wrqu,
+					 char *extra)
+{
+	int ret;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	rtw_set_macaddr_acl(padapter, param->u.mlme.command);
+
+	ret = 0;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
+		ret = -EFAULT;
+
+	err_free_param:
+		kfree(param);
+		return ret;
+}
+
+static int rtw_ioctl_acl_add_sta_pvt(struct net_device *dev,
+				     struct iw_request_info *info,
+				     union iwreq_data *wrqu,
+				     char *extra)
+{
+	int ret;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	ret = rtw_acl_add_sta(padapter, param->sta_addr);
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
+		ret = -EFAULT;
+
+	err_free_param:
+		kfree(param);
+		return ret;
+}
+
+static int rtw_ioctl_acl_remove_sta_pvt(struct net_device *dev,
+					struct iw_request_info *info,
+					union iwreq_data *wrqu,
+					char *extra)
+{
+	int ret;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	ret = rtw_acl_remove_sta(padapter, param->sta_addr);
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
+		ret = -EFAULT;
+
+	err_free_param:
+		kfree(param);
+		return ret;
+}
+
+static iw_handler rtw_handlers_private[] = {
+	NULL,                          /* Empty */
+	rtw_hostapd_sta_flush_pvt,     /* RTL871X_HOSTAPD_FLUSH */
+	rtw_add_sta_pvt,               /* RTL871X_HOSTAPD_ADD_STA */
+	rtw_del_sta_pvt,               /* RTL871X_HOSTAPD_REMOVE_STA */
+	rtw_ioctl_get_sta_data_pvt,    /* RTL871X_HOSTAPD_GET_INFO_STA */
+	rtw_get_sta_wpaie_pvt,         /* RTL871X_HOSTAPD_GET_WPAIE_STA */
+	rtw_set_encryption_pvt,        /* RTL871X_SET_ENCRYPTION */
+	NULL,                          /* RTL871X_GET_ENCRYPTION */
+	NULL,                          /* RTL871X_HOSTAPD_SET_FLAGS_STA */
+	NULL,                          /* RTL871X_HOSTAPD_GET_RID */
+	NULL,                          /* RTL871X_HOSTAPD_SET_RID */
+	NULL,                          /* RTL871X_HOSTAPD_SET_ASSOC_AP_ADDR */
+	NULL,                          /* RTL871X_HOSTAPD_SET_GENERIC_ELEMENT */
+	NULL,                          /* RTL871X_HOSTAPD_MLME */
+	NULL,                          /* RTL871X_HOSTAPD_SCAN_REQ */
+	NULL,                          /* RTL871X_HOSTAPD_STA_CLEAR_STATS */
+	rtw_set_beacon_pvt,            /* RTL871X_HOSTAPD_SET_BEACON */
+	rtw_set_wps_beacon_pvt,        /* RTL871X_HOSTAPD_SET_WPS_BEACON */
+	rtw_set_wps_probe_resp_pvt,    /* RTL871X_HOSTAPD_SET_WPS_PROBE_RESP */
+	rtw_set_wps_assoc_resp_pvt,    /* RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP */
+	rtw_set_hidden_ssid_pvt,       /* RTL871X_HOSTAPD_SET_HIDDEN_SSID */
+	rtw_ioctl_set_macaddr_acl_pvt, /* RTL871X_HOSTAPD_SET_MACADDR_ACL */
+	rtw_ioctl_acl_add_sta_pvt,     /* RTL871X_HOSTAPD_ACL_ADD_STA */
+	rtw_ioctl_acl_remove_sta_pvt,  /* RTL871X_HOSTAPD_ACL_REMOVE_STA */
+};
+
 static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
 {
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
@@ -3089,6 +4149,8 @@ static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
 struct iw_handler_def rtw_handlers_def = {
 	.standard = rtw_handlers,
 	.num_standard = ARRAY_SIZE(rtw_handlers),
+	.private = rtw_handlers_private,
+	.num_private = ARRAY_SIZE(rtw_handlers_private),
 	.get_wireless_stats = rtw_get_wireless_stats,
 };
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/2] staging: rtl8188eu: Fix private WEXT IOCTL calls
  2017-11-25  0:52 ` [PATCH 2/2] " ishraq.i.ashraf
@ 2017-11-25  4:40   ` Dan Carpenter
  2017-11-25 18:12     ` Ishraq Ibne Ashraf
  2017-11-26  0:45     ` Ishraq Ibne Ashraf
  0 siblings, 2 replies; 17+ messages in thread
From: Dan Carpenter @ 2017-11-25  4:40 UTC (permalink / raw)
  To: ishraq.i.ashraf
  Cc: gregkh, himanshujha199640, goudapatilk, insafonov, devel,
	linux-kernel, Johannes Berg

Thanks for doing this.

This needs to be folded in with the earlier patch you send and then
resend it as a V2 patch.
https://kernelnewbies.org/FirstKernelPatch#head-5c81b3c517a1d0bbc24f92594cb734e155fcbbcb

I added Johannes to the CC list again because this is sort of his
fault...  To be honest, I'm a little bit puzzled.  I would have thought
Johannes's change would have made some code unused and that we could
delete it now.  I haven't looked at this.

>  
> -	if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
> +	if (pmlmepriv->htpriv.ht_option == false)
> +		psta->htpriv.ht_option = false;
> +
> +	update_sta_info_apmode(padapter, psta);
> +
> +	ret = 0;
> +
> +	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
>  		ret = -EFAULT;
>  
> -	return ret;
> +	err_free_param:
> +		kfree(param);
> +		return ret;
>  }

Please keep the success path and failure paths separate like I did in
the example code that I wrote in my email.  Don't indent the labels.  It
should look like this:

	update_sta_info_apmode(padapter, psta);

	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
		ret = -EFAULT;
		goto err_free_param;
	}

	kfree(param);
	return 0;

err_free_param:
	kfree(param);
	return ret;

regards,
dan carpenter

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2] staging: rtl8188eu: Fix private WEXT IOCTL calls
  2017-11-25  1:29 ` [PATCH v2] " ishraq.i.ashraf
@ 2017-11-25  4:55   ` Dan Carpenter
  0 siblings, 0 replies; 17+ messages in thread
From: Dan Carpenter @ 2017-11-25  4:55 UTC (permalink / raw)
  To: ishraq.i.ashraf
  Cc: gregkh, devel, insafonov, goudapatilk, linux-kernel, himanshujha199640

On Sat, Nov 25, 2017 at 02:29:36AM +0100, ishraq.i.ashraf@gmail.com wrote:
> +
> +	ret = 0;
> +

Sorry, I wasn't clear before.  When I said don't initialize "ret" to
zero, I just meant that in that specific case we initialized "ret" and
then immediately reassigned it with:

	ret = some_function();
	if (ret)
		return ret;

In this case it's fine to set "ret = 0" at the start so that we don't
have to do it later.

> +	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
> +		ret = -EFAULT;
> +
> +	if (pwep)
> +		goto err_free_pwep_param;
> +
> +	err_free_param:
> +		kfree(param);
> +		return ret;
> +
> +	err_free_pwep_param:
> +		kfree(pwep);
> +		kfree(param);
> +		return ret;
> +}

Hm...  I said before that it's better to keep the error paths and
success path separate but in this case it's probabaly simpler to merge
them.

This one could look like this:

	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length))
		ret = -EFAULT;

free_pwep:
	kfree(pwep);
free_param:
	kfree(param);
	return ret;

There is no need for the if (pwep) conditions, because kfree() can
take a NULL pointer.  Some people would just use one label but I hate
that.  It looks like this:

free:
	kfree(pwep);
	kfree(param);
	return ret;

The reason, I hate it is because I don't like freeing things which have
not been allocated yet.  If you do it the normal kernel way then you
just have to keep track of the most recently allocated thing.

regards,
dan carpenter

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/2] staging: rtl8188eu: Fix private WEXT IOCTL calls
  2017-11-25  4:40   ` Dan Carpenter
@ 2017-11-25 18:12     ` Ishraq Ibne Ashraf
  2017-11-26  0:45     ` Ishraq Ibne Ashraf
  1 sibling, 0 replies; 17+ messages in thread
From: Ishraq Ibne Ashraf @ 2017-11-25 18:12 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: gregkh, himanshujha199640, goudapatilk, insafonov, devel,
	linux-kernel, Johannes Berg

Hi,

What was broken was private/device specific IOCTL calls implemented by this driver. The standard IOCTL calls worked and the driver worked as it was in client mode.

But in AP mode with hostapd (https://w1.fi/hostapd/) the rtl871xdrv driver of hostapd (which is required for using devices that use this driver in AP mode) invokes private/device specific IOCTL calls and in the existing driver they could only be invoked through the ndo_do_ioctl interface of the driver. Support for which was removed in the mentioned commit by Johannes Berg. Hence the driver stopped working in AP mode with hostapd using rtl871xdrv driver.

The solution was to implement equivalent versions of the existing private/device specific IOCTLs which will be invoked by the iw_handler_def interface.


Cheers,
Ishraq


On 11/25/2017 05:40 AM, Dan Carpenter wrote:
> I added Johannes to the CC list again because this is sort of his
> fault...  To be honest, I'm a little bit puzzled.  I would have thought
> Johannes's change would have made some code unused and that we could
> delete it now.  I haven't looked at this.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v3] staging: rtl8188eu: Fix private WEXT IOCTL calls
  2017-11-23  1:29 [PATCH] staging: rtl8188eu: Fix private WEXT IOCTL calls ishraq.i.ashraf
                   ` (2 preceding siblings ...)
  2017-11-25  1:29 ` [PATCH v2] " ishraq.i.ashraf
@ 2017-11-25 18:29 ` ishraq.i.ashraf
  2017-11-25 21:25   ` Dan Carpenter
                     ` (4 more replies)
  2017-11-26 20:45 ` [PATCH] " kbuild test robot
  2017-11-26 23:20 ` kbuild test robot
  5 siblings, 5 replies; 17+ messages in thread
From: ishraq.i.ashraf @ 2017-11-25 18:29 UTC (permalink / raw)
  To: gregkh
  Cc: himanshujha199640, goudapatilk, insafonov, dan.carpenter, devel,
	linux-kernel, johannes, Ishraq Ibne Ashraf

From: Ishraq Ibne Ashraf <ishraq.i.ashraf@gmail.com>

Commit 8bfb36766064 ("wireless: wext: remove ndo_do_ioctl fallback") breaks private WEXT
IOCTL calls of this driver as these are not invoked through ndo_do_ioctl
interface anymore. As a result hostapd stops working with this driver. In
this patch this problem is solved by implementing equivalent private IOCTL
functions of the existing ones which are accessed via iw_handler_def
interface.

Signed-off-by: Ishraq Ibne Ashraf <ishraq.i.ashraf@gmail.com>
---
 drivers/staging/rtl8188eu/os_dep/ioctl_linux.c | 1077 ++++++++++++++++++++++++
 1 file changed, 1077 insertions(+)

diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
index c0664dc..8d99f99 100644
--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
@@ -3061,6 +3061,1081 @@ static iw_handler rtw_handlers[] = {
 	NULL,					/*---hole---*/
 };
 
+static int get_private_handler_ieee_param(struct adapter *padapter,
+					  union iwreq_data *wrqu,
+					  void *param)
+{
+	/*
+	 * This function is expected to be called in master mode, which allows no
+	 * power saving. So we just check hw_init_completed.
+	 */
+	if (!padapter->hw_init_completed)
+		return -EPERM;
+
+	if (copy_from_user(param, wrqu->data.pointer, wrqu->data.length))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int rtw_hostapd_sta_flush_pvt(struct net_device *dev,
+				     struct iw_request_info *info,
+				     union iwreq_data *wrqu,
+				     char *extra)
+{
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	flush_all_cam_entry(padapter); /* Clear CAM. */
+	return rtw_sta_flush(padapter);
+}
+
+static int rtw_add_sta_pvt(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu,
+			   char *extra)
+{
+	int ret;
+	int flags;
+	struct sta_info *psta;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	DBG_88E("rtw_add_sta(aid =%d) =%pM\n",
+		param->u.add_sta.aid,
+		(param->sta_addr));
+
+	if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE))) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+	if (!psta) {
+		ret = -ENOMEM;
+		goto err_free_param;
+	}
+
+	flags = param->u.add_sta.flags;
+	psta->aid = param->u.add_sta.aid; /* aid = 1~2007. */
+
+	memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
+
+	/* Check WMM cap. */
+	if (WLAN_STA_WME&flags)
+		psta->qos_option = 1;
+	else
+		psta->qos_option = 0;
+
+	if (pmlmepriv->qospriv.qos_option == 0)
+		psta->qos_option = 0;
+
+	/* Check 802.11n HT cap. */
+	if (WLAN_STA_HT&flags) {
+		psta->htpriv.ht_option = true;
+		psta->qos_option = 1;
+		memcpy(&psta->htpriv.ht_cap,
+		       &param->u.add_sta.ht_cap,
+		       sizeof(struct ieee80211_ht_cap));
+	} else {
+		psta->htpriv.ht_option = false;
+	}
+
+	if (pmlmepriv->htpriv.ht_option == false)
+		psta->htpriv.ht_option = false;
+
+	update_sta_info_apmode(padapter, psta);
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
+		ret = -EFAULT;
+		goto err_free_param;
+	}
+
+	kfree(param);
+	return 0;
+
+err_free_param:
+	kfree(param);
+	return ret;
+}
+
+static int rtw_del_sta_pvt(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu,
+			   char *extra)
+{
+	int ret;
+	int updated;
+	struct sta_info *psta;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	DBG_88E("rtw_del_sta =%pM\n", (param->sta_addr));
+
+	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+	if (!psta) {
+		DBG_88E("rtw_del_sta(), sta has already been removed or never been added\n");
+		ret = -ENOMEM;
+		goto err_free_param;
+	}
+
+	spin_lock_bh(&pstapriv->asoc_list_lock);
+
+	updated = 0;
+
+	if (!list_empty(&psta->asoc_list)) {
+		list_del_init(&psta->asoc_list);
+		pstapriv->asoc_list_cnt--;
+		updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
+	}
+
+	spin_unlock_bh(&pstapriv->asoc_list_lock);
+	associated_clients_update(padapter, updated);
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
+		ret = -EFAULT;
+		goto err_free_param;
+	}
+
+	kfree(param);
+	return 0;
+
+err_free_param:
+	kfree(param);
+	return ret;
+}
+
+static int rtw_set_beacon_pvt(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu,
+			      char *extra)
+{
+	int ret;
+	int len;
+	unsigned char *pbuf;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	len = wrqu->data.length;
+	pbuf = param->u.bcn_ie.buf;
+
+	DBG_88E("%s, len =%d\n", __func__, len);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
+
+	if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
+		pstapriv->max_num_sta = NUM_STA;
+
+	if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) != _SUCCESS) { /*  12 = Param header, 2 = Not packed. */
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
+		ret = -EFAULT;
+		goto err_free_param;
+	}
+
+	kfree(param);
+	return 0;
+
+err_free_param:
+	kfree(param);
+	return ret;
+}
+
+static int rtw_set_encryption_pvt(struct net_device *dev,
+				  struct iw_request_info *info,
+				  union iwreq_data *wrqu,
+				  char *extra)
+{
+	int ret;
+	int param_len;
+	u32 wep_key_idx;
+	u32 wep_key_len;
+	u32 wep_total_len;
+	struct ieee_param *param;
+	struct sta_info *pbcmc_sta;
+	struct ndis_802_11_wep *pwep;
+	struct sta_info *psta = NULL;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct security_priv *psecuritypriv = &(padapter->securitypriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	param_len = wrqu->data.length;
+	param->u.crypt.err = 0;
+	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
+
+	if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {
+		ret =  -EINVAL;
+		goto err_free_param;
+	}
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		if (param->u.crypt.idx >= WEP_KEYS) {
+			ret = -EINVAL;
+			goto err_free_param;
+		}
+	} else {
+		psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+		if (!psta) {
+			DBG_88E("rtw_set_encryption(), sta has already been removed or never been added\n");
+			ret = -ENOMEM;
+			goto err_free_param;
+		}
+	}
+
+	if (strcmp(param->u.crypt.alg, "none") == 0 && (!psta)) {
+		/* TODO: Clear default encryption keys. */
+		DBG_88E("clear default encryption keys, keyid =%d\n",
+			param->u.crypt.idx);
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	if (strcmp(param->u.crypt.alg, "WEP") == 0 && (!psta)) {
+		DBG_88E("r871x_set_encryption, crypt.alg = WEP\n");
+
+		pwep = NULL;
+		wep_key_idx = param->u.crypt.idx;
+		wep_key_len = param->u.crypt.key_len;
+
+		DBG_88E("r871x_set_encryption, wep_key_idx=%d, len=%d\n",
+			wep_key_idx,
+			wep_key_len);
+
+		if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
+			ret = -EINVAL;
+			goto err_free_param;
+		}
+
+		if (wep_key_len > 0) {
+			wep_key_len = wep_key_len <= 5 ? 5 : 13;
+			wep_total_len = wep_key_len + offsetof(struct ndis_802_11_wep, KeyMaterial);
+
+			pwep = (struct ndis_802_11_wep *)kmalloc(wep_total_len, GFP_KERNEL);
+			if (!pwep) {
+				DBG_88E(" r871x_set_encryption: pwep allocate fail !!!\n");
+				ret = -ENOMEM;
+				goto err_free_param;
+			}
+
+			memset(pwep, 0, wep_total_len);
+			pwep->KeyLength = wep_key_len;
+			pwep->Length = wep_total_len;
+		}
+
+		pwep->KeyIndex = wep_key_idx;
+		memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
+
+		if (param->u.crypt.set_tx) {
+			DBG_88E("wep, set_tx = 1\n");
+
+			psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
+			psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
+			psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+
+			if (pwep->KeyLength == 13) {
+				psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
+				psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+			}
+
+			psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
+			memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]),
+			       pwep->KeyMaterial,
+			       pwep->KeyLength);
+			psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
+			set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
+		} else {
+			DBG_88E("wep, set_tx = 0\n");
+
+			/*
+			 * Don't update "psecuritypriv->dot11PrivacyAlgrthm" and
+			 * "psecuritypriv->dot11PrivacyKeyIndex = keyid", but rtw_set_key()
+			 * can to cam.
+			 */
+
+			memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]),
+			       pwep->KeyMaterial,
+			       pwep->KeyLength);
+			psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
+			set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
+		}
+
+		kfree(pwep);
+		goto free_param;
+	}
+
+	if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /*  Group key. */
+		if (param->u.crypt.set_tx == 1) {
+			if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+				DBG_88E("%s, set group_key, WEP\n", __func__);
+
+				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+				       param->u.crypt.key,
+				       min_t(u16, param->u.crypt.key_len,
+				       16));
+				psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+
+				if (param->u.crypt.key_len == 13)
+					psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+			} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+				DBG_88E("%s, set group_key, TKIP\n", __func__);
+
+				psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
+				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+				       param->u.crypt.key,
+				       min_t(u16, param->u.crypt.key_len,
+				       16));
+				/* Set mic key. */
+				memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey,
+				       &(param->u.crypt.key[16]),
+				       8);
+				memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey,
+				       &(param->u.crypt.key[24]),
+				       8);
+				psecuritypriv->busetkipkey = true;
+			} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+				DBG_88E("%s, set group_key, CCMP\n", __func__);
+
+				psecuritypriv->dot118021XGrpPrivacy = _AES_;
+				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+				       param->u.crypt.key,
+				       min_t(u16, param->u.crypt.key_len, 16));
+			} else {
+				DBG_88E("%s, set group_key, none\n", __func__);
+
+				psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+			}
+
+			psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
+			psecuritypriv->binstallGrpkey = true;
+			psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;
+			set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
+
+			pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+			if (pbcmc_sta) {
+				pbcmc_sta->ieee8021x_blocked = false;
+				pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; /* rx will use bmc_sta's dot118021XPrivacy. */
+			}
+		}
+
+		goto free_param;
+	}
+
+	if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x. */
+		if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+			if (param->u.crypt.set_tx == 1) {
+				memcpy(psta->dot118021x_UncstKey.skey,
+				       param->u.crypt.key,
+				       min_t(u16, param->u.crypt.key_len, 16));
+
+				if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+					DBG_88E("%s, set pairwise key, WEP\n", __func__);
+
+					psta->dot118021XPrivacy = _WEP40_;
+
+					if (param->u.crypt.key_len == 13)
+						psta->dot118021XPrivacy = _WEP104_;
+				} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+					DBG_88E("%s, set pairwise key, TKIP\n", __func__);
+
+					psta->dot118021XPrivacy = _TKIP_;
+					/* Set mic key. */
+					memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
+					memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
+					psecuritypriv->busetkipkey = true;
+				} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+					DBG_88E("%s, set pairwise key, CCMP\n", __func__);
+
+					psta->dot118021XPrivacy = _AES_;
+				} else {
+					DBG_88E("%s, set pairwise key, none\n", __func__);
+
+					psta->dot118021XPrivacy = _NO_PRIVACY_;
+				}
+
+				set_pairwise_key(padapter, psta);
+
+				psta->ieee8021x_blocked = false;
+			} else { /* Group key ? */
+				if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+					       param->u.crypt.key,
+					       min_t(u16, param->u.crypt.key_len, 16));
+					psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+
+					if (param->u.crypt.key_len == 13)
+						psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+				} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+					psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
+					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+					       param->u.crypt.key,
+					       min_t(u16, param->u.crypt.key_len, 16));
+					/* Set mic key. */
+					memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey,
+					       &(param->u.crypt.key[16]), 8);
+					memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey,
+					       &(param->u.crypt.key[24]), 8);
+					psecuritypriv->busetkipkey = true;
+				} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+					psecuritypriv->dot118021XGrpPrivacy = _AES_;
+					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+					       param->u.crypt.key,
+					       min_t(u16, param->u.crypt.key_len, 16));
+				} else {
+					psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+				}
+
+				psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
+				psecuritypriv->binstallGrpkey = true;
+				psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;
+				set_group_key(padapter,
+					      param->u.crypt.key,
+					      psecuritypriv->dot118021XGrpPrivacy,
+					      param->u.crypt.idx);
+
+				pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+				if (pbcmc_sta) {
+					pbcmc_sta->ieee8021x_blocked = false;
+					pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; /* rx will use bmc_sta's dot118021XPrivacy. */
+				}
+			}
+		}
+	}
+
+free_param:
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
+		ret = -EFAULT;
+		goto err_free_param;
+	}
+
+	kfree(param);
+	return 0;
+
+err_free_param:
+	kfree(param);
+	return ret;
+}
+
+static int rtw_get_sta_wpaie_pvt(struct net_device *dev,
+				 struct iw_request_info *info,
+				 union iwreq_data *wrqu,
+				 char *extra)
+{
+	int ret;
+	struct sta_info *psta;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (!ret)
+		goto err_free_param;
+
+	DBG_88E("rtw_get_sta_wpaie, sta_addr: %pM\n", (param->sta_addr));
+
+	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+	if (!psta) {
+		ret = -ENOMEM;
+		goto err_free_param;
+	}
+
+	if (psta->wpa_ie[0] == WLAN_EID_RSN ||
+	    psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
+		int copy_len;
+		int wpa_ie_len;
+
+		wpa_ie_len = psta->wpa_ie[1];
+		copy_len = min_t(int, wpa_ie_len + 2, sizeof(psta->wpa_ie));
+		param->u.wpa_ie.len = copy_len;
+		memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
+	} else {
+		DBG_88E("sta's wpa_ie is NONE\n");
+	}
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
+		ret = -EFAULT;
+		goto err_free_param;
+	}
+
+	kfree(param);
+	return 0;
+
+err_free_param:
+	kfree(param);
+	return ret;
+}
+
+static int rtw_set_wps_beacon_pvt(struct net_device *dev,
+				  struct iw_request_info *info,
+				  union iwreq_data *wrqu,
+				  char *extra)
+{
+	int ret;
+	int len;
+	int ie_len;
+	struct ieee_param *param;
+	unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return  -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	len = wrqu->data.length;
+
+	DBG_88E("%s, len =%d\n", __func__, len);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	kfree(pmlmepriv->wps_beacon_ie);
+	pmlmepriv->wps_beacon_ie = NULL;
+
+	ie_len = len-12-2; /* 12 = Param header, 2 = Not packed. */
+	if (ie_len > 0) {
+		pmlmepriv->wps_beacon_ie = kmalloc(ie_len, GFP_KERNEL);
+		if (!pmlmepriv->wps_beacon_ie) {
+			DBG_88E("%s()-%d: kmalloc() ERROR!\n", __func__, __LINE__);
+			ret = -EINVAL;
+			goto err_free_param;
+		}
+
+		pmlmepriv->wps_beacon_ie_len = ie_len;
+		memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
+		update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
+		pmlmeext->bstart_bss = true;
+	}
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
+		ret = -EFAULT;
+		goto err_free_wps_beacon_ie;
+	}
+
+	kfree(pmlmepriv->wps_beacon_ie);
+	kfree(param);
+	return 0;
+
+err_free_wps_beacon_ie:
+	kfree(pmlmepriv->wps_beacon_ie);
+
+err_free_param:
+	kfree(param);
+	return ret;
+}
+
+static int rtw_set_wps_probe_resp_pvt(struct net_device *dev,
+				      struct iw_request_info *info,
+				      union iwreq_data *wrqu,
+				      char *extra)
+{
+	int ret;
+	int len;
+	int ie_len;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	len = wrqu->data.length;
+
+	DBG_88E("%s, len =%d\n", __func__, len);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	kfree(pmlmepriv->wps_probe_resp_ie);
+	pmlmepriv->wps_probe_resp_ie = NULL;
+
+	ie_len = len-12-2; /* 12 = Param header, 2 = Not packed. */
+	if (ie_len > 0) {
+		pmlmepriv->wps_probe_resp_ie = kmalloc(ie_len, GFP_KERNEL);
+		if (!pmlmepriv->wps_probe_resp_ie) {
+			DBG_88E("%s()-%d: kmalloc() ERROR!\n", __func__, __LINE__);
+			ret = -EINVAL;
+			goto err_free_param;
+		}
+
+		pmlmepriv->wps_probe_resp_ie_len = ie_len;
+		memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
+	}
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
+		ret = -EFAULT;
+		goto err_free_wps_probe_resp_ie;
+	}
+
+	kfree(pmlmepriv->wps_probe_resp_ie);
+	kfree(param);
+	return 0;
+
+err_free_wps_probe_resp_ie:
+	kfree(pmlmepriv->wps_probe_resp_ie);
+
+err_free_param:
+	kfree(param);
+	return ret;
+}
+
+static int rtw_set_wps_assoc_resp_pvt(struct net_device *dev,
+				      struct iw_request_info *info,
+				      union iwreq_data *wrqu,
+				      char *extra)
+{
+	int ret;
+	int len;
+	int ie_len;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	len = wrqu->data.length;
+
+	DBG_88E("%s, len =%d\n", __func__, len);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	kfree(pmlmepriv->wps_assoc_resp_ie);
+	pmlmepriv->wps_assoc_resp_ie = NULL;
+
+	ie_len = len-12-2; /* 12 = Param header, 2 = Not packed. */
+	if (ie_len > 0) {
+		pmlmepriv->wps_assoc_resp_ie = kmalloc(ie_len, GFP_KERNEL);
+		if (!pmlmepriv->wps_assoc_resp_ie) {
+			DBG_88E("%s()-%d: kmalloc() ERROR!\n", __func__, __LINE__);
+			ret = -EINVAL;
+			goto err_free_param;
+		}
+
+		pmlmepriv->wps_assoc_resp_ie_len = ie_len;
+		memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
+	}
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
+		ret = -EFAULT;
+		goto err_free_wps_assoc_resp_ie;
+	}
+
+	kfree(pmlmepriv->wps_assoc_resp_ie);
+	kfree(param);
+	return 0;
+
+err_free_wps_assoc_resp_ie:
+	kfree(pmlmepriv->wps_assoc_resp_ie);
+
+err_free_param:
+	kfree(param);
+	return ret;
+}
+
+static int rtw_set_hidden_ssid_pvt(struct net_device *dev,
+				   struct iw_request_info *info,
+				   union iwreq_data *wrqu,
+				   char *extra)
+{
+	int ret;
+	u8 value;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	if (param->u.wpa_param.name != 0) /* Dummy test. */
+		DBG_88E("%s name(%u) != 0\n", __func__, param->u.wpa_param.name);
+
+	value = param->u.wpa_param.value;
+
+	/* Use the same definition of hostapd's ignore_broadcast_ssid. */
+	if (value != 1 && value != 2)
+		value = 0;
+
+	DBG_88E("%s value(%u)\n", __func__, value);
+
+	pmlmeinfo->hidden_ssid_mode = value;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
+		ret = -EFAULT;
+		goto err_free_param;
+	}
+
+	kfree(param);
+	return 0;
+
+err_free_param:
+	kfree(param);
+	return ret;
+}
+
+static int rtw_ioctl_get_sta_data_pvt(struct net_device *dev,
+				      struct iw_request_info *info,
+				      union iwreq_data *wrqu,
+				      char *extra)
+{
+	int ret;
+	struct sta_info *psta;
+	struct sta_data *psta_data;
+	struct ieee_param_ex *param_ex;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	param_ex = (struct ieee_param_ex *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param_ex)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param_ex);
+	if (ret)
+		goto err_free_param_ex;
+
+	psta_data = (struct sta_data *)param_ex->data;
+
+	DBG_88E("rtw_ioctl_get_sta_info, sta_addr: %pM\n", (param_ex->sta_addr));
+
+	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) {
+		ret = -EINVAL;
+		goto err_free_param_ex;
+	}
+
+	if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
+	    param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
+	    param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff) {
+		ret = -EINVAL;
+		goto err_free_param_ex;
+	}
+
+	psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
+	if (!psta) {
+		ret = -ENOMEM;
+		goto err_free_param_ex;
+	}
+
+	psta_data->aid = (u16)psta->aid;
+	psta_data->capability = psta->capability;
+	psta_data->flags = psta->flags;
+
+	/*
+	nonerp_set : BIT(0)
+	no_short_slot_time_set : BIT(1)
+	no_short_preamble_set : BIT(2)
+	no_ht_gf_set : BIT(3)
+	no_ht_set : BIT(4)
+	ht_20mhz_set : BIT(5)
+	*/
+
+	psta_data->sta_set = \
+		((psta->nonerp_set) |
+		(psta->no_short_slot_time_set << 1) |
+		(psta->no_short_preamble_set << 2) |
+		(psta->no_ht_gf_set << 3) |
+		(psta->no_ht_set << 4) |
+		(psta->ht_20mhz_set << 5));
+	psta_data->tx_supp_rates_len =  psta->bssratelen;
+	memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
+	memcpy(&psta_data->ht_cap,
+	       &psta->htpriv.ht_cap,
+	       sizeof(struct ieee80211_ht_cap));
+	psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
+	psta_data->rx_bytes = psta->sta_stats.rx_bytes;
+	psta_data->rx_drops = psta->sta_stats.rx_drops;
+	psta_data->tx_pkts = psta->sta_stats.tx_pkts;
+	psta_data->tx_bytes = psta->sta_stats.tx_bytes;
+	psta_data->tx_drops = psta->sta_stats.tx_drops;
+
+	if (copy_to_user(wrqu->data.pointer, param_ex, wrqu->data.length)) {
+		ret = -EFAULT;
+		goto err_free_param_ex;
+	}
+
+	kfree(param_ex);
+	return 0;
+
+err_free_param_ex:
+	kfree(param_ex);
+	return ret;
+}
+
+static int rtw_ioctl_set_macaddr_acl_pvt(struct net_device *dev,
+					 struct iw_request_info *info,
+					 union iwreq_data *wrqu,
+					 char *extra)
+{
+	int ret;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	rtw_set_macaddr_acl(padapter, param->u.mlme.command);
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
+		ret = -EFAULT;
+		goto err_free_param;
+	}
+
+	kfree(param);
+	return 0;
+
+err_free_param:
+	kfree(param);
+	return ret;
+}
+
+static int rtw_ioctl_acl_add_sta_pvt(struct net_device *dev,
+				     struct iw_request_info *info,
+				     union iwreq_data *wrqu,
+				     char *extra)
+{
+	int ret;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	ret = rtw_acl_add_sta(padapter, param->sta_addr);
+	if (ret)
+		goto err_free_param;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
+		ret = -EFAULT;
+		goto err_free_param;
+	}
+
+	kfree(param);
+	return 0;
+
+err_free_param:
+	kfree(param);
+	return ret;
+}
+
+static int rtw_ioctl_acl_remove_sta_pvt(struct net_device *dev,
+					struct iw_request_info *info,
+					union iwreq_data *wrqu,
+					char *extra)
+{
+	int ret;
+	struct ieee_param *param;
+	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	ret = get_private_handler_ieee_param(padapter, wrqu, param);
+	if (ret)
+		goto err_free_param;
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		ret = -EINVAL;
+		goto err_free_param;
+	}
+
+	ret = rtw_acl_remove_sta(padapter, param->sta_addr);
+	if (ret)
+		goto err_free_param;
+
+	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
+		ret = -EFAULT;
+		goto err_free_param;
+	}
+
+	kfree(param);
+	return 0;
+
+err_free_param:
+	kfree(param);
+	return ret;
+}
+
+static iw_handler rtw_handlers_private[] = {
+	NULL,                          /* Empty */
+	rtw_hostapd_sta_flush_pvt,     /* RTL871X_HOSTAPD_FLUSH */
+	rtw_add_sta_pvt,               /* RTL871X_HOSTAPD_ADD_STA */
+	rtw_del_sta_pvt,               /* RTL871X_HOSTAPD_REMOVE_STA */
+	rtw_ioctl_get_sta_data_pvt,    /* RTL871X_HOSTAPD_GET_INFO_STA */
+	rtw_get_sta_wpaie_pvt,         /* RTL871X_HOSTAPD_GET_WPAIE_STA */
+	rtw_set_encryption_pvt,        /* RTL871X_SET_ENCRYPTION */
+	NULL,                          /* RTL871X_GET_ENCRYPTION */
+	NULL,                          /* RTL871X_HOSTAPD_SET_FLAGS_STA */
+	NULL,                          /* RTL871X_HOSTAPD_GET_RID */
+	NULL,                          /* RTL871X_HOSTAPD_SET_RID */
+	NULL,                          /* RTL871X_HOSTAPD_SET_ASSOC_AP_ADDR */
+	NULL,                          /* RTL871X_HOSTAPD_SET_GENERIC_ELEMENT */
+	NULL,                          /* RTL871X_HOSTAPD_MLME */
+	NULL,                          /* RTL871X_HOSTAPD_SCAN_REQ */
+	NULL,                          /* RTL871X_HOSTAPD_STA_CLEAR_STATS */
+	rtw_set_beacon_pvt,            /* RTL871X_HOSTAPD_SET_BEACON */
+	rtw_set_wps_beacon_pvt,        /* RTL871X_HOSTAPD_SET_WPS_BEACON */
+	rtw_set_wps_probe_resp_pvt,    /* RTL871X_HOSTAPD_SET_WPS_PROBE_RESP */
+	rtw_set_wps_assoc_resp_pvt,    /* RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP */
+	rtw_set_hidden_ssid_pvt,       /* RTL871X_HOSTAPD_SET_HIDDEN_SSID */
+	rtw_ioctl_set_macaddr_acl_pvt, /* RTL871X_HOSTAPD_SET_MACADDR_ACL */
+	rtw_ioctl_acl_add_sta_pvt,     /* RTL871X_HOSTAPD_ACL_ADD_STA */
+	rtw_ioctl_acl_remove_sta_pvt,  /* RTL871X_HOSTAPD_ACL_REMOVE_STA */
+};
+
 static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
 {
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
@@ -3089,6 +4164,8 @@ static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
 struct iw_handler_def rtw_handlers_def = {
 	.standard = rtw_handlers,
 	.num_standard = ARRAY_SIZE(rtw_handlers),
+	.private = rtw_handlers_private,
+	.num_private = ARRAY_SIZE(rtw_handlers_private),
 	.get_wireless_stats = rtw_get_wireless_stats,
 };
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH v3] staging: rtl8188eu: Fix private WEXT IOCTL calls
  2017-11-25 18:29 ` [PATCH v3] " ishraq.i.ashraf
@ 2017-11-25 21:25   ` Dan Carpenter
  2017-11-27 11:24   ` Johannes Berg
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 17+ messages in thread
From: Dan Carpenter @ 2017-11-25 21:25 UTC (permalink / raw)
  To: ishraq.i.ashraf
  Cc: gregkh, devel, insafonov, goudapatilk, linux-kernel,
	himanshujha199640, johannes

Thanks.  This is looking *much* better...

On Sat, Nov 25, 2017 at 07:29:41PM +0100, ishraq.i.ashraf@gmail.com wrote:
> From: Ishraq Ibne Ashraf <ishraq.i.ashraf@gmail.com>
> 
> Commit 8bfb36766064 ("wireless: wext: remove ndo_do_ioctl fallback") breaks private WEXT
> IOCTL calls of this driver as these are not invoked through ndo_do_ioctl
> interface anymore. As a result hostapd stops working with this driver. In
> this patch this problem is solved by implementing equivalent private IOCTL
> functions of the existing ones which are accessed via iw_handler_def
> interface.
> 
> Signed-off-by: Ishraq Ibne Ashraf <ishraq.i.ashraf@gmail.com>
> ---
>  drivers/staging/rtl8188eu/os_dep/ioctl_linux.c | 1077 ++++++++++++++++++++++++
>  1 file changed, 1077 insertions(+)
> 
> diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
> index c0664dc..8d99f99 100644
> --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
> +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
> @@ -3061,6 +3061,1081 @@ static iw_handler rtw_handlers[] = {
>  	NULL,					/*---hole---*/
>  };
>  
> +static int get_private_handler_ieee_param(struct adapter *padapter,
> +					  union iwreq_data *wrqu,
> +					  void *param)
> +{
> +	/*
> +	 * This function is expected to be called in master mode, which allows no
> +	 * power saving. So we just check hw_init_completed.
> +	 */
> +	if (!padapter->hw_init_completed)
> +		return -EPERM;

This check doesn't belong here.  ->hw_init_completed is set to true in
rtw_hal_init() and false in rtw_hal_deinit().  Can it ever be false
here?  I really doubt it and if I'm wrong then we are pretty screwed
already...  Anyway, move the check or delete it.  Then this function and
the kmalloc() can be replaced with memdup_user().

> +
> +	if (copy_from_user(param, wrqu->data.pointer, wrqu->data.length))
> +		return -EFAULT;
> +
> +	return 0;
> +}
> +
> +static int rtw_hostapd_sta_flush_pvt(struct net_device *dev,
> +				     struct iw_request_info *info,
> +				     union iwreq_data *wrqu,
> +				     char *extra)
> +{
> +	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);

Add a blank line after declarations.

> +	flush_all_cam_entry(padapter); /* Clear CAM. */
> +	return rtw_sta_flush(padapter);
> +}
> +
> +static int rtw_add_sta_pvt(struct net_device *dev,
> +			   struct iw_request_info *info,
> +			   union iwreq_data *wrqu,
> +			   char *extra)
> +{
> +	int ret;
> +	int flags;
> +	struct sta_info *psta;
> +	struct ieee_param *param;
> +	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
> +	struct sta_priv *pstapriv = &padapter->stapriv;
> +	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
> +
> +	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
> +	if (!param)
> +		return -ENOMEM;
> +
> +	ret = get_private_handler_ieee_param(padapter, wrqu, param);
> +	if (ret)
> +		goto err_free_param;

Then these lines become:

	param = memdup_user(wrqu->data.pointer, wrqu->data.length);
	if (IS_ERR(param))
		return PTR_ERR(param);

> +
> +	DBG_88E("rtw_add_sta(aid =%d) =%pM\n",
> +		param->u.add_sta.aid,
> +		(param->sta_addr));
> +
> +	if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE))) {
> +		ret = -EINVAL;
> +		goto err_free_param;
> +	}
> +
> +	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
> +	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
> +	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
> +		ret = -EINVAL;
> +		goto err_free_param;
> +	}
> +
> +	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
> +	if (!psta) {
> +		ret = -ENOMEM;
> +		goto err_free_param;
> +	}
> +
> +	flags = param->u.add_sta.flags;
> +	psta->aid = param->u.add_sta.aid; /* aid = 1~2007. */
> +
> +	memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
> +
> +	/* Check WMM cap. */
> +	if (WLAN_STA_WME&flags)


Add spaces around the & and reverse the order.

	if (flags & WLAN_STA_HT) {

> +		psta->qos_option = 1;
> +	else
> +		psta->qos_option = 0;
> +
> +	if (pmlmepriv->qospriv.qos_option == 0)
> +		psta->qos_option = 0;
> +
> +	/* Check 802.11n HT cap. */
> +	if (WLAN_STA_HT&flags) {

Add spaces and reverse.

> +		psta->htpriv.ht_option = true;
> +		psta->qos_option = 1;
> +		memcpy(&psta->htpriv.ht_cap,
> +		       &param->u.add_sta.ht_cap,
> +		       sizeof(struct ieee80211_ht_cap));
> +	} else {
> +		psta->htpriv.ht_option = false;
> +	}
> +
> +	if (pmlmepriv->htpriv.ht_option == false)
> +		psta->htpriv.ht_option = false;
> +
> +	update_sta_info_apmode(padapter, psta);
> +
> +	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
> +		ret = -EFAULT;
> +		goto err_free_param;
> +	}
> +
> +	kfree(param);
> +	return 0;
> +
> +err_free_param:
> +	kfree(param);
> +	return ret;
> +}
> +
> +static int rtw_del_sta_pvt(struct net_device *dev,
> +			   struct iw_request_info *info,
> +			   union iwreq_data *wrqu,
> +			   char *extra)
> +{
> +	int ret;
> +	int updated;
> +	struct sta_info *psta;
> +	struct ieee_param *param;
> +	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
> +	struct sta_priv *pstapriv = &padapter->stapriv;
> +	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
> +
> +	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
> +	if (!param)
> +		return -ENOMEM;
> +
> +	ret = get_private_handler_ieee_param(padapter, wrqu, param);
> +	if (ret)
> +		goto err_free_param;

memdup_user();

> +
> +	DBG_88E("rtw_del_sta =%pM\n", (param->sta_addr));
> +
> +	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) {
> +		ret = -EINVAL;
> +		goto err_free_param;
> +	}
> +
> +	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
> +	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
> +	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
> +		ret = -EINVAL;
> +		goto err_free_param;
> +	}
> +
> +	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
> +	if (!psta) {
> +		DBG_88E("rtw_del_sta(), sta has already been removed or never been added\n");
> +		ret = -ENOMEM;
> +		goto err_free_param;
> +	}
> +
> +	spin_lock_bh(&pstapriv->asoc_list_lock);
> +
> +	updated = 0;
> +
> +	if (!list_empty(&psta->asoc_list)) {
> +		list_del_init(&psta->asoc_list);
> +		pstapriv->asoc_list_cnt--;
> +		updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
> +	}
> +
> +	spin_unlock_bh(&pstapriv->asoc_list_lock);
> +	associated_clients_update(padapter, updated);
> +
> +	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
> +		ret = -EFAULT;
> +		goto err_free_param;
> +	}
> +
> +	kfree(param);
> +	return 0;
> +
> +err_free_param:
> +	kfree(param);
> +	return ret;
> +}
> +
> +static int rtw_set_beacon_pvt(struct net_device *dev,
> +			      struct iw_request_info *info,
> +			      union iwreq_data *wrqu,
> +			      char *extra)
> +{
> +	int ret;
> +	int len;
> +	unsigned char *pbuf;
> +	struct ieee_param *param;
> +	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
> +	struct sta_priv *pstapriv = &padapter->stapriv;
> +	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
> +
> +	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
> +	if (!param)
> +		return -ENOMEM;
> +
> +	ret = get_private_handler_ieee_param(padapter, wrqu, param);
> +	if (ret)
> +		goto err_free_param;
> +
> +	len = wrqu->data.length;
> +	pbuf = param->u.bcn_ie.buf;
> +
> +	DBG_88E("%s, len =%d\n", __func__, len);
> +
> +	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
> +		ret = -EINVAL;
> +		goto err_free_param;
> +	}
> +
> +	memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);

It's concerning to me that we are using reserved memory...  Reserved
means we it is saved for the future and we aren't supposed to use it.
Maybe the name needs changed.  Use a sizeof() instead of a 2.

> +
> +	if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
> +		pstapriv->max_num_sta = NUM_STA;
> +
> +	if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) != _SUCCESS) { /*  12 = Param header, 2 = Not packed. */

The white space isn't right here.  There are two spaces after the comma.

> +		ret = -EINVAL;
> +		goto err_free_param;
> +	}
> +
> +	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
> +		ret = -EFAULT;
> +		goto err_free_param;
> +	}
> +
> +	kfree(param);
> +	return 0;
> +
> +err_free_param:
> +	kfree(param);
> +	return ret;
> +}
> +
> +static int rtw_set_encryption_pvt(struct net_device *dev,
> +				  struct iw_request_info *info,
> +				  union iwreq_data *wrqu,
> +				  char *extra)
> +{
> +	int ret;
> +	int param_len;
> +	u32 wep_key_idx;
> +	u32 wep_key_len;
> +	u32 wep_total_len;
> +	struct ieee_param *param;
> +	struct sta_info *pbcmc_sta;
> +	struct ndis_802_11_wep *pwep;
> +	struct sta_info *psta = NULL;
> +	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
> +	struct sta_priv *pstapriv = &padapter->stapriv;
> +	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
> +	struct security_priv *psecuritypriv = &(padapter->securitypriv);
> +
> +	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
> +	if (!param)
> +		return -ENOMEM;
> +
> +	ret = get_private_handler_ieee_param(padapter, wrqu, param);
> +	if (ret)
> +		goto err_free_param;
> +
> +	param_len = wrqu->data.length;
> +	param->u.crypt.err = 0;
> +	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';

This is problematica because how do we know that wrqu->data.length is
large enough to hold a ieee_param struct?  There should probably be a
check like:

	if (wrqu->data.length < sizeof(*param))
		return -EINVAL;

Probably all the functions should have this.


> +
> +	if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {

We're checking here but we have already written a NUL terminator
possibly beyond the end of the buffer.  There are two spaces after the
!=.

> +		ret =  -EINVAL;
> +		goto err_free_param;
> +	}
> +
> +	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
> +	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
> +	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
> +		if (param->u.crypt.idx >= WEP_KEYS) {
> +			ret = -EINVAL;
> +			goto err_free_param;
> +		}
> +	} else {
> +		psta = rtw_get_stainfo(pstapriv, param->sta_addr);
> +		if (!psta) {
> +			DBG_88E("rtw_set_encryption(), sta has already been removed or never been added\n");
> +			ret = -ENOMEM;
> +			goto err_free_param;
> +		}
> +	}
> +
> +	if (strcmp(param->u.crypt.alg, "none") == 0 && (!psta)) {
                                                       ^    ^
Remove the extra parens.

> +		/* TODO: Clear default encryption keys. */
> +		DBG_88E("clear default encryption keys, keyid =%d\n",
> +			param->u.crypt.idx);
> +		ret = -EINVAL;
> +		goto err_free_param;
> +	}
> +
> +	if (strcmp(param->u.crypt.alg, "WEP") == 0 && (!psta)) {
                                                      ^     ^
Extra parens.

> +		DBG_88E("r871x_set_encryption, crypt.alg = WEP\n");
> +
> +		pwep = NULL;
> +		wep_key_idx = param->u.crypt.idx;
> +		wep_key_len = param->u.crypt.key_len;
> +
> +		DBG_88E("r871x_set_encryption, wep_key_idx=%d, len=%d\n",
> +			wep_key_idx,
> +			wep_key_len);
> +
> +		if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
                    ^                       ^    ^                ^
Remove the extra parens.  wep_key_len is unsigned so it can't be less
than zero. 


> +			ret = -EINVAL;
> +			goto err_free_param;
> +		}
> +
> +		if (wep_key_len > 0) {

No need to check this because we just checked on the line before.

> +			wep_key_len = wep_key_len <= 5 ? 5 : 13;
> +			wep_total_len = wep_key_len + offsetof(struct ndis_802_11_wep, KeyMaterial);
> +
> +			pwep = (struct ndis_802_11_wep *)kmalloc(wep_total_len, GFP_KERNEL);
> +			if (!pwep) {
> +				DBG_88E(" r871x_set_encryption: pwep allocate fail !!!\n");

Remove space at the start of printk

> +				ret = -ENOMEM;
> +				goto err_free_param;
> +			}
> +
> +			memset(pwep, 0, wep_total_len);
> +			pwep->KeyLength = wep_key_len;
> +			pwep->Length = wep_total_len;
> +		}
> +
> +		pwep->KeyIndex = wep_key_idx;
> +		memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);

Extra space after comma

> +
> +		if (param->u.crypt.set_tx) {
> +			DBG_88E("wep, set_tx = 1\n");
> +
> +			psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
> +			psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
> +			psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
> +
> +			if (pwep->KeyLength == 13) {
> +				psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
> +				psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
> +			}
> +
> +			psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
> +			memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]),
                                ^                                               ^
Remove the extra parens

> +			       pwep->KeyMaterial,
> +			       pwep->KeyLength);
> +			psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
> +			set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
> +		} else {
> +			DBG_88E("wep, set_tx = 0\n");
> +
> +			/*
> +			 * Don't update "psecuritypriv->dot11PrivacyAlgrthm" and
> +			 * "psecuritypriv->dot11PrivacyKeyIndex = keyid", but rtw_set_key()
> +			 * can to cam.
> +			 */
> +
> +			memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]),
                                ^                                               ^
Extra parens

> +			       pwep->KeyMaterial,
> +			       pwep->KeyLength);
> +			psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
> +			set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
> +		}
> +
> +		kfree(pwep);
> +		goto free_param;
> +	}
> +
> +	if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /*  Group key. */
> +		if (param->u.crypt.set_tx == 1) {
> +			if (strcmp(param->u.crypt.alg, "WEP") == 0) {
> +				DBG_88E("%s, set group_key, WEP\n", __func__);
> +
> +				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
> +				       param->u.crypt.key,
> +				       min_t(u16, param->u.crypt.key_len,
> +				       16));
> +				psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
> +
> +				if (param->u.crypt.key_len == 13)
> +					psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
> +			} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
> +				DBG_88E("%s, set group_key, TKIP\n", __func__);
> +
> +				psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
> +				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
> +				       param->u.crypt.key,
> +				       min_t(u16, param->u.crypt.key_len,
> +				       16));
> +				/* Set mic key. */
> +				memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey,
> +				       &(param->u.crypt.key[16]),
> +				       8);
> +				memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey,
> +				       &(param->u.crypt.key[24]),
> +				       8);
> +				psecuritypriv->busetkipkey = true;
> +			} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
> +				DBG_88E("%s, set group_key, CCMP\n", __func__);
> +
> +				psecuritypriv->dot118021XGrpPrivacy = _AES_;
> +				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
> +				       param->u.crypt.key,
> +				       min_t(u16, param->u.crypt.key_len, 16));
> +			} else {
> +				DBG_88E("%s, set group_key, none\n", __func__);
> +
> +				psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
> +			}
> +
> +			psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
> +			psecuritypriv->binstallGrpkey = true;
> +			psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;
> +			set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
> +
> +			pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
> +			if (pbcmc_sta) {
> +				pbcmc_sta->ieee8021x_blocked = false;
> +				pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; /* rx will use bmc_sta's dot118021XPrivacy. */
> +			}
> +		}
> +
> +		goto free_param;
> +	}
> +
> +	if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x. */
> +		if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
> +			if (param->u.crypt.set_tx == 1) {
> +				memcpy(psta->dot118021x_UncstKey.skey,
> +				       param->u.crypt.key,
> +				       min_t(u16, param->u.crypt.key_len, 16));
> +
> +				if (strcmp(param->u.crypt.alg, "WEP") == 0) {
> +					DBG_88E("%s, set pairwise key, WEP\n", __func__);
> +
> +					psta->dot118021XPrivacy = _WEP40_;
> +
> +					if (param->u.crypt.key_len == 13)
> +						psta->dot118021XPrivacy = _WEP104_;
> +				} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
> +					DBG_88E("%s, set pairwise key, TKIP\n", __func__);
> +
> +					psta->dot118021XPrivacy = _TKIP_;
> +					/* Set mic key. */
> +					memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
> +					memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
> +					psecuritypriv->busetkipkey = true;
> +				} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
> +					DBG_88E("%s, set pairwise key, CCMP\n", __func__);
> +
> +					psta->dot118021XPrivacy = _AES_;
> +				} else {
> +					DBG_88E("%s, set pairwise key, none\n", __func__);
> +
> +					psta->dot118021XPrivacy = _NO_PRIVACY_;
> +				}
> +
> +				set_pairwise_key(padapter, psta);
> +
> +				psta->ieee8021x_blocked = false;
> +			} else { /* Group key ? */
> +				if (strcmp(param->u.crypt.alg, "WEP") == 0) {
> +					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
> +					       param->u.crypt.key,
> +					       min_t(u16, param->u.crypt.key_len, 16));
> +					psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
> +
> +					if (param->u.crypt.key_len == 13)
> +						psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
> +				} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
> +					psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
> +					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
> +					       param->u.crypt.key,
> +					       min_t(u16, param->u.crypt.key_len, 16));
> +					/* Set mic key. */
> +					memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey,
> +					       &(param->u.crypt.key[16]), 8);
                                                ^                      ^
Extra parens

> +					memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey,
> +					       &(param->u.crypt.key[24]), 8);
                                                ^                      ^
Extra parens

> +					psecuritypriv->busetkipkey = true;
> +				} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
> +					psecuritypriv->dot118021XGrpPrivacy = _AES_;
> +					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
> +					       param->u.crypt.key,
> +					       min_t(u16, param->u.crypt.key_len, 16));
> +				} else {
> +					psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
> +				}
> +
> +				psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
> +				psecuritypriv->binstallGrpkey = true;
> +				psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;
> +				set_group_key(padapter,
> +					      param->u.crypt.key,
> +					      psecuritypriv->dot118021XGrpPrivacy,
> +					      param->u.crypt.idx);
> +
> +				pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
> +				if (pbcmc_sta) {
> +					pbcmc_sta->ieee8021x_blocked = false;
> +					pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; /* rx will use bmc_sta's dot118021XPrivacy. */
> +				}
> +			}
> +		}
> +	}
> +
> +free_param:
> +	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
> +		ret = -EFAULT;
> +		goto err_free_param;
> +	}
> +
> +	kfree(param);
> +	return 0;
> +
> +err_free_param:
> +	kfree(param);
> +	return ret;
> +}
> +
> +static int rtw_get_sta_wpaie_pvt(struct net_device *dev,
> +				 struct iw_request_info *info,
> +				 union iwreq_data *wrqu,
> +				 char *extra)
> +{
> +	int ret;
> +	struct sta_info *psta;
> +	struct ieee_param *param;
> +	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
> +	struct sta_priv *pstapriv = &padapter->stapriv;
> +	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
> +
> +	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
> +	if (!param)
> +		return -ENOMEM;
> +
> +	ret = get_private_handler_ieee_param(padapter, wrqu, param);
> +	if (!ret)
> +		goto err_free_param;


memdup_user()

> +
> +	DBG_88E("rtw_get_sta_wpaie, sta_addr: %pM\n", (param->sta_addr));
> +
> +	if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) {
> +		ret = -EINVAL;
> +		goto err_free_param;
> +	}
> +
> +	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
> +	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
> +	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
> +		ret = -EINVAL;
> +		goto err_free_param;
> +	}
> +
> +	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
> +	if (!psta) {
> +		ret = -ENOMEM;
> +		goto err_free_param;
> +	}
> +
> +	if (psta->wpa_ie[0] == WLAN_EID_RSN ||
> +	    psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
> +		int copy_len;
> +		int wpa_ie_len;
> +
> +		wpa_ie_len = psta->wpa_ie[1];
> +		copy_len = min_t(int, wpa_ie_len + 2, sizeof(psta->wpa_ie));
> +		param->u.wpa_ie.len = copy_len;
> +		memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
> +	} else {
> +		DBG_88E("sta's wpa_ie is NONE\n");
> +	}
> +
> +	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
> +		ret = -EFAULT;
> +		goto err_free_param;
> +	}
> +
> +	kfree(param);
> +	return 0;
> +
> +err_free_param:
> +	kfree(param);
> +	return ret;
> +}
> +
> +static int rtw_set_wps_beacon_pvt(struct net_device *dev,
> +				  struct iw_request_info *info,
> +				  union iwreq_data *wrqu,
> +				  char *extra)
> +{
> +	int ret;
> +	int len;
> +	int ie_len;
> +	struct ieee_param *param;
> +	unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
> +	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
> +	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
> +	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
> +
> +	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
> +	if (!param)
> +		return  -ENOMEM;
> +
> +	ret = get_private_handler_ieee_param(padapter, wrqu, param);
> +	if (ret)
> +		goto err_free_param;

memdup_user()

> +
> +	len = wrqu->data.length;
> +
> +	DBG_88E("%s, len =%d\n", __func__, len);
> +
> +	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
> +		ret = -EINVAL;
> +		goto err_free_param;
> +	}
> +
> +	kfree(pmlmepriv->wps_beacon_ie);
> +	pmlmepriv->wps_beacon_ie = NULL;
> +
> +	ie_len = len-12-2; /* 12 = Param header, 2 = Not packed. */

Add spaces around opperators:

	ie_len = len - 12 - 2;

> +	if (ie_len > 0) {
> +		pmlmepriv->wps_beacon_ie = kmalloc(ie_len, GFP_KERNEL);
> +		if (!pmlmepriv->wps_beacon_ie) {
> +			DBG_88E("%s()-%d: kmalloc() ERROR!\n", __func__, __LINE__);

Delete this printk after a kmalloc().  Kmalloc() already has a stack
trace built-in.

> +			ret = -EINVAL;
> +			goto err_free_param;
> +		}
> +
> +		pmlmepriv->wps_beacon_ie_len = ie_len;
> +		memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
> +		update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
> +		pmlmeext->bstart_bss = true;
> +	}
> +
> +	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
> +		ret = -EFAULT;
> +		goto err_free_wps_beacon_ie;
> +	}
> +
> +	kfree(pmlmepriv->wps_beacon_ie);
> +	kfree(param);
> +	return 0;
> +
> +err_free_wps_beacon_ie:
> +	kfree(pmlmepriv->wps_beacon_ie);
> +
> +err_free_param:
> +	kfree(param);
> +	return ret;
> +}
> +
> +static int rtw_set_wps_probe_resp_pvt(struct net_device *dev,
> +				      struct iw_request_info *info,
> +				      union iwreq_data *wrqu,
> +				      char *extra)
> +{
> +	int ret;
> +	int len;
> +	int ie_len;
> +	struct ieee_param *param;
> +	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
> +	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
> +
> +	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
> +	if (!param)
> +		return -ENOMEM;
> +
> +	ret = get_private_handler_ieee_param(padapter, wrqu, param);
> +	if (ret)
> +		goto err_free_param;
> +

memdup_user()

> +	len = wrqu->data.length;
> +
> +	DBG_88E("%s, len =%d\n", __func__, len);
> +
> +	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
> +		ret = -EINVAL;
> +		goto err_free_param;
> +	}
> +
> +	kfree(pmlmepriv->wps_probe_resp_ie);
> +	pmlmepriv->wps_probe_resp_ie = NULL;

We should have a local variable instead of using
pmlmepriv->wps_probe_resp_ie.  The problem with a shared variable is
that there is no locking and it could have a race and use after free and
it's possibly a security issue.  Also it looks like it could buffer
overflow as well because we're re-allocating it with different sizes.

> +
> +	ie_len = len-12-2; /* 12 = Param header, 2 = Not packed. */

Add spaces

> +	if (ie_len > 0) {

Say ie_len is <= 0, isn't that -EINVAL?

> +		pmlmepriv->wps_probe_resp_ie = kmalloc(ie_len, GFP_KERNEL);
> +		if (!pmlmepriv->wps_probe_resp_ie) {
> +			DBG_88E("%s()-%d: kmalloc() ERROR!\n", __func__, __LINE__);
> +			ret = -EINVAL;
> +			goto err_free_param;
> +		}
> +
> +		pmlmepriv->wps_probe_resp_ie_len = ie_len;
> +		memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
> +	}
> +
> +	if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
> +		ret = -EFAULT;
> +		goto err_free_wps_probe_resp_ie;
> +	}
> +
> +	kfree(pmlmepriv->wps_probe_resp_ie);
> +	kfree(param);
> +	return 0;
> +
> +err_free_wps_probe_resp_ie:
> +	kfree(pmlmepriv->wps_probe_resp_ie);
> +
> +err_free_param:
> +	kfree(param);
> +	return ret;
> +}
> +
> +static int rtw_set_wps_assoc_resp_pvt(struct net_device *dev,
> +				      struct iw_request_info *info,
> +				      union iwreq_data *wrqu,
> +				      char *extra)
> +{
> +	int ret;
> +	int len;
> +	int ie_len;
> +	struct ieee_param *param;
> +	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
> +	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
> +
> +	param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
> +	if (!param)
> +		return -ENOMEM;
> +
> +	ret = get_private_handler_ieee_param(padapter, wrqu, param);
> +	if (ret)
> +		goto err_free_param;

memdup_user()

> +
> +	len = wrqu->data.length;
> +
> +	DBG_88E("%s, len =%d\n", __func__, len);
> +
> +	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
> +		ret = -EINVAL;
> +		goto err_free_param;
> +	}
> +
> +	kfree(pmlmepriv->wps_assoc_resp_ie);
> +	pmlmepriv->wps_assoc_resp_ie = NULL;

Use local variable

I have to go to sleep now, but I can't stress enough how much better
this version is than v1 and v2.  Thanks very much.

regards,
dan carpenter

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/2] staging: rtl8188eu: Fix private WEXT IOCTL calls
  2017-11-25  4:40   ` Dan Carpenter
  2017-11-25 18:12     ` Ishraq Ibne Ashraf
@ 2017-11-26  0:45     ` Ishraq Ibne Ashraf
  2017-11-27 11:33       ` Johannes Berg
  1 sibling, 1 reply; 17+ messages in thread
From: Ishraq Ibne Ashraf @ 2017-11-26  0:45 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: gregkh, himanshujha199640, goudapatilk, insafonov, devel,
	linux-kernel, Johannes Berg

Hi,

What was broken was private/device specific IOCTL calls implemented by this driver. The standard IOCTL calls worked and the driver worked as it was in client mode.

But in AP mode with hostapd (https://w1.fi/hostapd/) the rtl871xdrv driver of hostapd (which is required for using devices that use this driver in AP mode) invokes private/device specific IOCTL calls and in the existing driver they could only be invoked through the ndo_do_ioctl interface of the driver. Support for which was removed in the mentioned commit by Johannes Berg. Hence the driver stopped working in AP mode with hostapd using rtl871xdrv driver.

The solution was to implement equivalent versions of the existing private/device specific IOCTLs which will be invoked by the iw_handler_def interface.


Cheers,
Ishraq


On 11/25/2017 05:40 AM, Dan Carpenter wrote:
> I added Johannes to the CC list again because this is sort of his
> fault...  To be honest, I'm a little bit puzzled.  I would have thought
> Johannes's change would have made some code unused and that we could
> delete it now.  I haven't looked at this.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] staging: rtl8188eu: Fix private WEXT IOCTL calls
  2017-11-23  1:29 [PATCH] staging: rtl8188eu: Fix private WEXT IOCTL calls ishraq.i.ashraf
                   ` (3 preceding siblings ...)
  2017-11-25 18:29 ` [PATCH v3] " ishraq.i.ashraf
@ 2017-11-26 20:45 ` kbuild test robot
  2017-11-26 23:20 ` kbuild test robot
  5 siblings, 0 replies; 17+ messages in thread
From: kbuild test robot @ 2017-11-26 20:45 UTC (permalink / raw)
  To: ishraq.i.ashraf
  Cc: kbuild-all, gregkh, himanshujha199640, goudapatilk, insafonov,
	devel, linux-kernel, Ishraq Ibne Ashraf

[-- Attachment #1: Type: text/plain, Size: 18486 bytes --]

Hi Ishraq,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on staging/staging-testing]
[also build test ERROR on v4.14 next-20171124]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/ishraq-i-ashraf-gmail-com/staging-rtl8188eu-Fix-private-WEXT-IOCTL-calls/20171126-052554
config: x86_64-randconfig-n0-11270329 (attached as .config)
compiler: gcc-7 (Debian 7.2.0-12) 7.2.1 20171025
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All error/warnings (new ones prefixed by >>):

   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_hostapd_sta_flush_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3101:9: error: implicit declaration of function 'rtw_sta_flush'; did you mean 'rtw_set_auth'? [-Werror=implicit-function-declaration]
     return rtw_sta_flush(padapter);
            ^~~~~~~~~~~~~
            rtw_set_auth
   In file included from include/linux/kernel.h:14:0,
                    from include/linux/skbuff.h:17,
                    from include/linux/if_ether.h:23,
                    from include/linux/ieee80211.h:21,
                    from drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:17:
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_add_sta_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3133:49: error: 'union <anonymous>' has no member named 'add_sta'
     DBG_88E("rtw_add_sta(aid =%d) =%pM\n", param->u.add_sta.aid, (param->sta_addr));
                                                    ^
   include/linux/printk.h:310:34: note: in definition of macro 'pr_info'
     printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
                                     ^~~~~~~~~~~
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3133:2: note: in expansion of macro 'DBG_88E'
     DBG_88E("rtw_add_sta(aid =%d) =%pM\n", param->u.add_sta.aid, (param->sta_addr));
     ^~~~~~~
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3145:23: error: 'union <anonymous>' has no member named 'add_sta'
      int flags = param->u.add_sta.flags;
                          ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3146:23: error: 'union <anonymous>' has no member named 'add_sta'
      psta->aid = param->u.add_sta.aid; // aid = 1~2007.
                          ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3148:36: error: 'union <anonymous>' has no member named 'add_sta'
      memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
                                       ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3151:7: error: 'WLAN_STA_WME' undeclared (first use in this function); did you mean 'SCAN_STATE'?
      if (WLAN_STA_WME&flags)
          ^~~~~~~~~~~~
          SCAN_STATE
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3151:7: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3160:7: error: 'WLAN_STA_HT' undeclared (first use in this function); did you mean 'WLAN_STA_WME'?
      if (WLAN_STA_HT&flags) {
          ^~~~~~~~~~~
          WLAN_STA_WME
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3164:20: error: 'union <anonymous>' has no member named 'add_sta'
              &param->u.add_sta.ht_cap,
                       ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3173:3: error: implicit declaration of function 'update_sta_info_apmode'; did you mean 'update_sta_info'? [-Werror=implicit-function-declaration]
      update_sta_info_apmode(padapter, psta);
      ^~~~~~~~~~~~~~~~~~~~~~
      update_sta_info
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_del_sta_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3229:14: error: 'struct sta_priv' has no member named 'asoc_list_cnt'; did you mean 'asoc_list_lock'?
       pstapriv->asoc_list_cnt--;
                 ^~~~~~~~~~~~~
                 asoc_list_lock
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3230:14: error: implicit declaration of function 'ap_free_sta'; did you mean '__kfree_skb'? [-Werror=implicit-function-declaration]
       updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
                 ^~~~~~~~~~~
                 __kfree_skb
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3233:3: error: implicit declaration of function 'associated_clients_update' [-Werror=implicit-function-declaration]
      associated_clients_update(padapter, updated);
      ^~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_set_beacon_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3276:18: error: 'union <anonymous>' has no member named 'bcn_ie'; did you mean 'wpa_ie'?
     pbuf = param->u.bcn_ie.buf;
                     ^~~~~~
                     wpa_ie
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3283:18: error: 'struct sta_priv' has no member named 'max_num_sta'
     memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
                     ^~
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3283:42: error: 'union <anonymous>' has no member named 'bcn_ie'; did you mean 'wpa_ie'?
     memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
                                             ^~~~~~
                                             wpa_ie
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3285:15: error: 'struct sta_priv' has no member named 'max_num_sta'
     if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
                  ^~
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3285:52: error: 'struct sta_priv' has no member named 'max_num_sta'
     if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
                                                       ^~
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3286:11: error: 'struct sta_priv' has no member named 'max_num_sta'
      pstapriv->max_num_sta = NUM_STA;
              ^~
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3288:6: error: implicit declaration of function 'rtw_check_beacon_data'; did you mean 'rtw_set_beacon_pvt'? [-Werror=implicit-function-declaration]
     if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) == _SUCCESS) //  12 = Param header, 2 = Not packed.
         ^~~~~~~~~~~~~~~~~~~~~
         rtw_set_beacon_pvt
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_set_encryption_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3412:4: error: implicit declaration of function 'set_wep_key'; did you mean 'rtw_set_key'? [-Werror=implicit-function-declaration]
       set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
       ^~~~~~~~~~~
       rtw_set_key
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3476:4: error: implicit declaration of function 'set_group_key'; did you mean 'set_groups'? [-Werror=implicit-function-declaration]
       set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
       ^~~~~~~~~~~~~
       set_groups
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3517:5: error: implicit declaration of function 'set_pairwise_key'; did you mean 'set_dma_reserve'? [-Werror=implicit-function-declaration]
        set_pairwise_key(padapter, psta);
        ^~~~~~~~~~~~~~~~
        set_dma_reserve
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_get_sta_wpaie_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3621:11: error: 'struct sta_info' has no member named 'wpa_ie'
      if (psta->wpa_ie[0] == WLAN_EID_RSN ||
              ^~
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3622:11: error: 'struct sta_info' has no member named 'wpa_ie'
          psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
              ^~
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3626:26: error: 'struct sta_info' has no member named 'wpa_ie'
            wpa_ie_len = psta->wpa_ie[1];
                             ^~
   In file included from include/linux/skbuff.h:17:0,
                    from include/linux/if_ether.h:23,
                    from include/linux/ieee80211.h:21,
                    from drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:17:
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3627:58: error: 'struct sta_info' has no member named 'wpa_ie'
            copy_len = min_t(int, wpa_ie_len + 2, sizeof(psta->wpa_ie));
                                                             ^
   include/linux/kernel.h:790:13: note: in definition of macro '__min'
     t2 min2 = (y);     \
                ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3627:20: note: in expansion of macro 'min_t'
            copy_len = min_t(int, wpa_ie_len + 2, sizeof(psta->wpa_ie));
                       ^~~~~
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3629:46: error: 'struct sta_info' has no member named 'wpa_ie'
            memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
                                                 ^~
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_set_wps_beacon_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3682:19: error: 'struct mlme_priv' has no member named 'wps_beacon_ie'; did you mean 'wps_probe_req_ie'?
     kfree(pmlmepriv->wps_beacon_ie);
                      ^~~~~~~~~~~~~
                      wps_probe_req_ie
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3683:13: error: 'struct mlme_priv' has no member named 'wps_beacon_ie'; did you mean 'wps_probe_req_ie'?
     pmlmepriv->wps_beacon_ie = NULL;
                ^~~~~~~~~~~~~
                wps_probe_req_ie
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3686:14: error: 'struct mlme_priv' has no member named 'wps_beacon_ie'; did you mean 'wps_probe_req_ie'?
      pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
                 ^~~~~~~~~~~~~
                 wps_probe_req_ie
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3687:14: error: 'struct mlme_priv' has no member named 'wps_beacon_ie_len'; did you mean 'wps_probe_req_ie_len'?
      pmlmepriv->wps_beacon_ie_len = ie_len;
                 ^~~~~~~~~~~~~~~~~
                 wps_probe_req_ie_len
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3688:19: error: 'struct mlme_priv' has no member named 'wps_beacon_ie'; did you mean 'wps_probe_req_ie'?
      if (!pmlmepriv->wps_beacon_ie) {
                      ^~~~~~~~~~~~~
                      wps_probe_req_ie
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3693:21: error: 'struct mlme_priv' has no member named 'wps_beacon_ie'; did you mean 'wps_probe_req_ie'?
      memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
                        ^~~~~~~~~~~~~
                        wps_probe_req_ie
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3693:45: error: 'union <anonymous>' has no member named 'bcn_ie'; did you mean 'wpa_ie'?
      memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
                                                ^~~~~~
                                                wpa_ie
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3694:3: error: implicit declaration of function 'update_beacon'; did you mean 'update_beacon_info'? [-Werror=implicit-function-declaration]
      update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
      ^~~~~~~~~~~~~
      update_beacon_info

vim +3101 drivers/staging/rtl8188eu/os_dep/ioctl_linux.c

  3089	
  3090	static int rtw_hostapd_sta_flush_pvt(struct net_device *dev,
  3091		struct iw_request_info *info,
  3092		union iwreq_data *wrqu,
  3093		char *extra)
  3094	{
  3095		struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
  3096	
  3097		DBG_88E("%s\n", __func__);
  3098	
  3099		flush_all_cam_entry(padapter); // Clear CAM.
  3100	
> 3101		return rtw_sta_flush(padapter);
  3102	}
  3103	
  3104	static int rtw_add_sta_pvt(struct net_device *dev,
  3105		struct iw_request_info *info,
  3106		union iwreq_data *wrqu,
  3107		char *extra)
  3108	{
  3109		int ret = 0;
  3110		struct sta_info *psta = NULL;
  3111		struct ieee_param *param = NULL;
  3112		struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
  3113		struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  3114		struct sta_priv *pstapriv = &padapter->stapriv;
  3115	
  3116		param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
  3117	
  3118		if (!param) {
  3119			DBG_88E(" rtw_add_sta: ieee_param allocate fail !!!\n");
  3120	
  3121			return -ENOMEM;
  3122		}
  3123	
  3124		ret = get_private_handler_ieee_param(padapter, wrqu, param);
  3125	
  3126		if (ret != 0) {
  3127			kfree(param);
  3128			DBG_88E(" rtw_add_sta: ieee_param get fail !!!\n");
  3129	
  3130			return ret;
  3131		}
  3132	
> 3133		DBG_88E("rtw_add_sta(aid =%d) =%pM\n", param->u.add_sta.aid, (param->sta_addr));
  3134	
  3135		if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)))
  3136			return -EINVAL;
  3137	
  3138		if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
  3139		    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
  3140		    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
  3141		      return -EINVAL;
  3142	
  3143		psta = rtw_get_stainfo(pstapriv, param->sta_addr);
  3144		if (psta) {
> 3145			int flags = param->u.add_sta.flags;
  3146			psta->aid = param->u.add_sta.aid; // aid = 1~2007.
  3147	
> 3148			memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
  3149	
  3150			// Check WMM cap.
> 3151			if (WLAN_STA_WME&flags)
  3152				psta->qos_option = 1;
  3153			else
  3154				psta->qos_option = 0;
  3155	
  3156			if (pmlmepriv->qospriv.qos_option == 0)
  3157				psta->qos_option = 0;
  3158	
  3159			// Check 802.11n HT cap.
> 3160			if (WLAN_STA_HT&flags) {
  3161				psta->htpriv.ht_option = true;
  3162				psta->qos_option = 1;
  3163				memcpy(&psta->htpriv.ht_cap,
> 3164				       &param->u.add_sta.ht_cap,
  3165				       sizeof(struct ieee80211_ht_cap));
  3166			} else {
  3167				psta->htpriv.ht_option = false;
  3168			}
  3169	
  3170			if (pmlmepriv->htpriv.ht_option == false)
  3171				psta->htpriv.ht_option = false;
  3172	
> 3173			update_sta_info_apmode(padapter, psta);
  3174		} else {
  3175			ret = -ENOMEM;
  3176		}
  3177	
  3178		if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
  3179			ret = -EFAULT;
  3180	
  3181		return ret;
  3182	}
  3183	
  3184	static int rtw_del_sta_pvt(struct net_device *dev,
  3185		struct iw_request_info *info,
  3186		union iwreq_data *wrqu,
  3187		char *extra)
  3188	{
  3189		int ret = 0;
  3190		struct sta_info *psta = NULL;
  3191		struct ieee_param *param = NULL;
  3192		struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
  3193		struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  3194		struct sta_priv *pstapriv = &padapter->stapriv;
  3195		int updated = 0;
  3196	
  3197		param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
  3198	
  3199		if (!param) {
  3200			DBG_88E(" rtw_del_sta: ieee_param allocate fail !!!\n");
  3201	
  3202			return -ENOMEM;
  3203		}
  3204	
  3205		ret = get_private_handler_ieee_param(padapter, wrqu, param);
  3206	
  3207		if (ret != 0) {
  3208			kfree(param);
  3209			DBG_88E(" rtw_del_sta: ieee_param get fail !!!\n");
  3210	
  3211			return ret;
  3212		}
  3213	
  3214		DBG_88E("rtw_del_sta =%pM\n", (param->sta_addr));
  3215	
  3216		if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
  3217			return -EINVAL;
  3218	
  3219		if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
  3220		    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
  3221		    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
  3222		      return -EINVAL;
  3223	
  3224		psta = rtw_get_stainfo(pstapriv, param->sta_addr);
  3225		if (psta) {
  3226			spin_lock_bh(&pstapriv->asoc_list_lock);
  3227			if (!list_empty(&psta->asoc_list)) {
  3228				list_del_init(&psta->asoc_list);
> 3229				pstapriv->asoc_list_cnt--;
> 3230				updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
  3231			}
  3232			spin_unlock_bh(&pstapriv->asoc_list_lock);
> 3233			associated_clients_update(padapter, updated);
  3234			psta = NULL;
  3235		} else {
  3236			DBG_88E("rtw_del_sta(), sta has already been removed or never been added\n");
  3237		}
  3238	
  3239		if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
  3240			ret = -EFAULT;
  3241	
  3242		return ret;
  3243	}
  3244	
  3245	static int rtw_set_beacon_pvt(struct net_device *dev,
  3246		struct iw_request_info *info,
  3247		union iwreq_data *wrqu,
  3248		char *extra)
  3249	{
  3250		int ret = 0;
  3251		int len = 0;
  3252		unsigned char *pbuf = NULL;
  3253		struct ieee_param *param = NULL;
  3254		struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
  3255		struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  3256		struct sta_priv *pstapriv = &padapter->stapriv;
  3257	
  3258		param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
  3259	
  3260		if (!param) {
  3261			DBG_88E(" rtw_set_beacon: ieee_param allocate fail !!!\n");
  3262	
  3263			return -ENOMEM;
  3264		}
  3265	
  3266		ret = get_private_handler_ieee_param(padapter, wrqu, param);
  3267	
  3268		if (ret != 0) {
  3269			kfree(param);
  3270			DBG_88E(" rtw_set_beacon: ieee_param get fail !!!\n");
  3271	
  3272			return ret;
  3273		}
  3274	
  3275		len = wrqu->data.length;
> 3276		pbuf = param->u.bcn_ie.buf;
  3277	
  3278		DBG_88E("%s, len =%d\n", __func__, len);
  3279	
  3280		if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
  3281			return -EINVAL;
  3282	
> 3283		memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
  3284	
> 3285		if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
> 3286			pstapriv->max_num_sta = NUM_STA;
  3287	
> 3288		if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) == _SUCCESS) //  12 = Param header, 2 = Not packed.
  3289			ret = 0;
  3290		else
  3291			ret = -EINVAL;
  3292	
  3293		if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
  3294			ret = -EFAULT;
  3295	
  3296		return ret;
  3297	}
  3298	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 32003 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] staging: rtl8188eu: Fix private WEXT IOCTL calls
  2017-11-23  1:29 [PATCH] staging: rtl8188eu: Fix private WEXT IOCTL calls ishraq.i.ashraf
                   ` (4 preceding siblings ...)
  2017-11-26 20:45 ` [PATCH] " kbuild test robot
@ 2017-11-26 23:20 ` kbuild test robot
  5 siblings, 0 replies; 17+ messages in thread
From: kbuild test robot @ 2017-11-26 23:20 UTC (permalink / raw)
  To: ishraq.i.ashraf
  Cc: kbuild-all, gregkh, himanshujha199640, goudapatilk, insafonov,
	devel, linux-kernel, Ishraq Ibne Ashraf

[-- Attachment #1: Type: text/plain, Size: 22781 bytes --]

Hi Ishraq,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on staging/staging-testing]
[also build test ERROR on v4.14 next-20171124]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/ishraq-i-ashraf-gmail-com/staging-rtl8188eu-Fix-private-WEXT-IOCTL-calls/20171126-052554
config: x86_64-randconfig-u0-11270543 (attached as .config)
compiler: gcc-5 (Debian 5.5.0-3) 5.4.1 20171010
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_hostapd_sta_flush_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3101:9: error: implicit declaration of function 'rtw_sta_flush' [-Werror=implicit-function-declaration]
     return rtw_sta_flush(padapter);
            ^
   In file included from include/linux/kernel.h:14:0,
                    from include/linux/skbuff.h:17,
                    from include/linux/if_ether.h:23,
                    from include/linux/ieee80211.h:21,
                    from drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:17:
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_add_sta_pvt':
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3133:49: error: 'union <anonymous>' has no member named 'add_sta'
     DBG_88E("rtw_add_sta(aid =%d) =%pM\n", param->u.add_sta.aid, (param->sta_addr));
                                                    ^
   include/linux/printk.h:310:34: note: in definition of macro 'pr_info'
     printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
                                     ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3133:2: note: in expansion of macro 'DBG_88E'
     DBG_88E("rtw_add_sta(aid =%d) =%pM\n", param->u.add_sta.aid, (param->sta_addr));
     ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3145:23: error: 'union <anonymous>' has no member named 'add_sta'
      int flags = param->u.add_sta.flags;
                          ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3146:23: error: 'union <anonymous>' has no member named 'add_sta'
      psta->aid = param->u.add_sta.aid; // aid = 1~2007.
                          ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3148:36: error: 'union <anonymous>' has no member named 'add_sta'
      memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
                                       ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3151:7: error: 'WLAN_STA_WME' undeclared (first use in this function)
      if (WLAN_STA_WME&flags)
          ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3151:7: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3160:7: error: 'WLAN_STA_HT' undeclared (first use in this function)
      if (WLAN_STA_HT&flags) {
          ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3164:20: error: 'union <anonymous>' has no member named 'add_sta'
              &param->u.add_sta.ht_cap,
                       ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3173:3: error: implicit declaration of function 'update_sta_info_apmode' [-Werror=implicit-function-declaration]
      update_sta_info_apmode(padapter, psta);
      ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_del_sta_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3229:12: error: 'struct sta_priv' has no member named 'asoc_list_cnt'
       pstapriv->asoc_list_cnt--;
               ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3230:14: error: implicit declaration of function 'ap_free_sta' [-Werror=implicit-function-declaration]
       updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
                 ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3233:3: error: implicit declaration of function 'associated_clients_update' [-Werror=implicit-function-declaration]
      associated_clients_update(padapter, updated);
      ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_set_beacon_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3276:17: error: 'union <anonymous>' has no member named 'bcn_ie'
     pbuf = param->u.bcn_ie.buf;
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3283:18: error: 'struct sta_priv' has no member named 'max_num_sta'
     memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
                     ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3283:41: error: 'union <anonymous>' has no member named 'bcn_ie'
     memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
                                            ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3285:15: error: 'struct sta_priv' has no member named 'max_num_sta'
     if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
                  ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3285:52: error: 'struct sta_priv' has no member named 'max_num_sta'
     if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
                                                       ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3286:11: error: 'struct sta_priv' has no member named 'max_num_sta'
      pstapriv->max_num_sta = NUM_STA;
              ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3288:6: error: implicit declaration of function 'rtw_check_beacon_data' [-Werror=implicit-function-declaration]
     if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) == _SUCCESS) //  12 = Param header, 2 = Not packed.
         ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_set_encryption_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3412:4: error: implicit declaration of function 'set_wep_key' [-Werror=implicit-function-declaration]
       set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
       ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3476:4: error: implicit declaration of function 'set_group_key' [-Werror=implicit-function-declaration]
       set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
       ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3517:5: error: implicit declaration of function 'set_pairwise_key' [-Werror=implicit-function-declaration]
        set_pairwise_key(padapter, psta);
        ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_get_sta_wpaie_pvt':
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3621:11: error: 'struct sta_info' has no member named 'wpa_ie'
      if (psta->wpa_ie[0] == WLAN_EID_RSN ||
              ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3622:11: error: 'struct sta_info' has no member named 'wpa_ie'
          psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
              ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3626:26: error: 'struct sta_info' has no member named 'wpa_ie'
            wpa_ie_len = psta->wpa_ie[1];
                             ^
   In file included from include/linux/skbuff.h:17:0,
                    from include/linux/if_ether.h:23,
                    from include/linux/ieee80211.h:21,
                    from drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:17:
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3627:58: error: 'struct sta_info' has no member named 'wpa_ie'
            copy_len = min_t(int, wpa_ie_len + 2, sizeof(psta->wpa_ie));
                                                             ^
   include/linux/kernel.h:790:13: note: in definition of macro '__min'
     t2 min2 = (y);     \
                ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3627:20: note: in expansion of macro 'min_t'
            copy_len = min_t(int, wpa_ie_len + 2, sizeof(psta->wpa_ie));
                       ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3629:46: error: 'struct sta_info' has no member named 'wpa_ie'
            memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
                                                 ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_set_wps_beacon_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3682:17: error: 'struct mlme_priv' has no member named 'wps_beacon_ie'
     kfree(pmlmepriv->wps_beacon_ie);
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3683:11: error: 'struct mlme_priv' has no member named 'wps_beacon_ie'
     pmlmepriv->wps_beacon_ie = NULL;
              ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3686:12: error: 'struct mlme_priv' has no member named 'wps_beacon_ie'
      pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
               ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3687:12: error: 'struct mlme_priv' has no member named 'wps_beacon_ie_len'
      pmlmepriv->wps_beacon_ie_len = ie_len;
               ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3688:17: error: 'struct mlme_priv' has no member named 'wps_beacon_ie'
      if (!pmlmepriv->wps_beacon_ie) {
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3693:19: error: 'struct mlme_priv' has no member named 'wps_beacon_ie'
      memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
                      ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3693:44: error: 'union <anonymous>' has no member named 'bcn_ie'
      memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
                                               ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3694:3: error: implicit declaration of function 'update_beacon' [-Werror=implicit-function-declaration]
      update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
      ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3696:11: error: 'struct mlme_ext_priv' has no member named 'bstart_bss'
      pmlmeext->bstart_bss = true;
              ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_set_wps_probe_resp_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3742:17: error: 'struct mlme_priv' has no member named 'wps_probe_resp_ie'
     kfree(pmlmepriv->wps_probe_resp_ie);
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3743:11: error: 'struct mlme_priv' has no member named 'wps_probe_resp_ie'
     pmlmepriv->wps_probe_resp_ie = NULL;
              ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3746:12: error: 'struct mlme_priv' has no member named 'wps_probe_resp_ie'
      pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
               ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3747:12: error: 'struct mlme_priv' has no member named 'wps_probe_resp_ie_len'
      pmlmepriv->wps_probe_resp_ie_len = ie_len;
               ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3748:17: error: 'struct mlme_priv' has no member named 'wps_probe_resp_ie'
      if (!pmlmepriv->wps_probe_resp_ie) {
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3752:19: error: 'struct mlme_priv' has no member named 'wps_probe_resp_ie'
      memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
                      ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3752:48: error: 'union <anonymous>' has no member named 'bcn_ie'
      memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
                                                   ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_set_wps_assoc_resp_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3798:17: error: 'struct mlme_priv' has no member named 'wps_assoc_resp_ie'
     kfree(pmlmepriv->wps_assoc_resp_ie);
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3799:11: error: 'struct mlme_priv' has no member named 'wps_assoc_resp_ie'
     pmlmepriv->wps_assoc_resp_ie = NULL;
              ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3802:12: error: 'struct mlme_priv' has no member named 'wps_assoc_resp_ie'
      pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
               ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3803:12: error: 'struct mlme_priv' has no member named 'wps_assoc_resp_ie_len'
      pmlmepriv->wps_assoc_resp_ie_len = ie_len;
               ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3804:17: error: 'struct mlme_priv' has no member named 'wps_assoc_resp_ie'
      if (!pmlmepriv->wps_assoc_resp_ie) {
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3809:19: error: 'struct mlme_priv' has no member named 'wps_assoc_resp_ie'
      memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
                      ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3809:48: error: 'union <anonymous>' has no member named 'bcn_ie'
      memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
                                                   ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_ioctl_get_sta_data_pvt':
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3898:41: error: dereferencing pointer to incomplete type 'struct ieee_param_ex'
     psta_data = (struct sta_data *)param_ex->data;
                                            ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3912:12: error: dereferencing pointer to incomplete type 'struct sta_data'
      psta_data->aid = (u16)psta->aid;
               ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3913:31: error: 'struct sta_info' has no member named 'capability'
      psta_data->capability = psta->capability;
                                  ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3914:26: error: 'struct sta_info' has no member named 'flags'
      psta_data->flags = psta->flags;
                             ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3926:10: error: 'struct sta_info' has no member named 'nonerp_set'
       ((psta->nonerp_set) |
             ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3927:9: error: 'struct sta_info' has no member named 'no_short_slot_time_set'
       (psta->no_short_slot_time_set << 1) |
            ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3928:9: error: 'struct sta_info' has no member named 'no_short_preamble_set'
       (psta->no_short_preamble_set << 2) |
            ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3929:9: error: 'struct sta_info' has no member named 'no_ht_gf_set'
       (psta->no_ht_gf_set << 3) |
            ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3930:9: error: 'struct sta_info' has no member named 'no_ht_set'
       (psta->no_ht_set << 4) |
            ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3931:9: error: 'struct sta_info' has no member named 'ht_20mhz_set'
       (psta->ht_20mhz_set << 5));
            ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_ioctl_set_macaddr_acl_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3983:2: error: implicit declaration of function 'rtw_set_macaddr_acl' [-Werror=implicit-function-declaration]
     rtw_set_macaddr_acl(padapter, param->u.mlme.command);
     ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_ioctl_acl_add_sta_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:4026:8: error: implicit declaration of function 'rtw_acl_add_sta' [-Werror=implicit-function-declaration]
     ret = rtw_acl_add_sta(padapter, param->sta_addr);
           ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_ioctl_acl_remove_sta_pvt':

vim +/rtw_sta_flush +3101 drivers/staging/rtl8188eu/os_dep/ioctl_linux.c

  3089	
  3090	static int rtw_hostapd_sta_flush_pvt(struct net_device *dev,
  3091		struct iw_request_info *info,
  3092		union iwreq_data *wrqu,
  3093		char *extra)
  3094	{
  3095		struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
  3096	
  3097		DBG_88E("%s\n", __func__);
  3098	
  3099		flush_all_cam_entry(padapter); // Clear CAM.
  3100	
> 3101		return rtw_sta_flush(padapter);
  3102	}
  3103	
  3104	static int rtw_add_sta_pvt(struct net_device *dev,
  3105		struct iw_request_info *info,
  3106		union iwreq_data *wrqu,
  3107		char *extra)
  3108	{
  3109		int ret = 0;
  3110		struct sta_info *psta = NULL;
  3111		struct ieee_param *param = NULL;
  3112		struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
  3113		struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  3114		struct sta_priv *pstapriv = &padapter->stapriv;
  3115	
  3116		param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
  3117	
  3118		if (!param) {
  3119			DBG_88E(" rtw_add_sta: ieee_param allocate fail !!!\n");
  3120	
  3121			return -ENOMEM;
  3122		}
  3123	
  3124		ret = get_private_handler_ieee_param(padapter, wrqu, param);
  3125	
  3126		if (ret != 0) {
  3127			kfree(param);
  3128			DBG_88E(" rtw_add_sta: ieee_param get fail !!!\n");
  3129	
  3130			return ret;
  3131		}
  3132	
  3133		DBG_88E("rtw_add_sta(aid =%d) =%pM\n", param->u.add_sta.aid, (param->sta_addr));
  3134	
  3135		if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)))
  3136			return -EINVAL;
  3137	
  3138		if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
  3139		    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
  3140		    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
  3141		      return -EINVAL;
  3142	
  3143		psta = rtw_get_stainfo(pstapriv, param->sta_addr);
  3144		if (psta) {
> 3145			int flags = param->u.add_sta.flags;
  3146			psta->aid = param->u.add_sta.aid; // aid = 1~2007.
  3147	
> 3148			memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
  3149	
  3150			// Check WMM cap.
> 3151			if (WLAN_STA_WME&flags)
  3152				psta->qos_option = 1;
  3153			else
  3154				psta->qos_option = 0;
  3155	
  3156			if (pmlmepriv->qospriv.qos_option == 0)
  3157				psta->qos_option = 0;
  3158	
  3159			// Check 802.11n HT cap.
> 3160			if (WLAN_STA_HT&flags) {
  3161				psta->htpriv.ht_option = true;
  3162				psta->qos_option = 1;
  3163				memcpy(&psta->htpriv.ht_cap,
> 3164				       &param->u.add_sta.ht_cap,
  3165				       sizeof(struct ieee80211_ht_cap));
  3166			} else {
  3167				psta->htpriv.ht_option = false;
  3168			}
  3169	
  3170			if (pmlmepriv->htpriv.ht_option == false)
  3171				psta->htpriv.ht_option = false;
  3172	
> 3173			update_sta_info_apmode(padapter, psta);
  3174		} else {
  3175			ret = -ENOMEM;
  3176		}
  3177	
  3178		if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
  3179			ret = -EFAULT;
  3180	
  3181		return ret;
  3182	}
  3183	
  3184	static int rtw_del_sta_pvt(struct net_device *dev,
  3185		struct iw_request_info *info,
  3186		union iwreq_data *wrqu,
  3187		char *extra)
  3188	{
  3189		int ret = 0;
  3190		struct sta_info *psta = NULL;
  3191		struct ieee_param *param = NULL;
  3192		struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
  3193		struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  3194		struct sta_priv *pstapriv = &padapter->stapriv;
  3195		int updated = 0;
  3196	
  3197		param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
  3198	
  3199		if (!param) {
  3200			DBG_88E(" rtw_del_sta: ieee_param allocate fail !!!\n");
  3201	
  3202			return -ENOMEM;
  3203		}
  3204	
  3205		ret = get_private_handler_ieee_param(padapter, wrqu, param);
  3206	
  3207		if (ret != 0) {
  3208			kfree(param);
  3209			DBG_88E(" rtw_del_sta: ieee_param get fail !!!\n");
  3210	
  3211			return ret;
  3212		}
  3213	
  3214		DBG_88E("rtw_del_sta =%pM\n", (param->sta_addr));
  3215	
  3216		if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
  3217			return -EINVAL;
  3218	
  3219		if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
  3220		    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
  3221		    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
  3222		      return -EINVAL;
  3223	
  3224		psta = rtw_get_stainfo(pstapriv, param->sta_addr);
  3225		if (psta) {
  3226			spin_lock_bh(&pstapriv->asoc_list_lock);
  3227			if (!list_empty(&psta->asoc_list)) {
  3228				list_del_init(&psta->asoc_list);
> 3229				pstapriv->asoc_list_cnt--;
> 3230				updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
  3231			}
  3232			spin_unlock_bh(&pstapriv->asoc_list_lock);
  3233			associated_clients_update(padapter, updated);
  3234			psta = NULL;
  3235		} else {
  3236			DBG_88E("rtw_del_sta(), sta has already been removed or never been added\n");
  3237		}
  3238	
  3239		if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
  3240			ret = -EFAULT;
  3241	
  3242		return ret;
  3243	}
  3244	
  3245	static int rtw_set_beacon_pvt(struct net_device *dev,
  3246		struct iw_request_info *info,
  3247		union iwreq_data *wrqu,
  3248		char *extra)
  3249	{
  3250		int ret = 0;
  3251		int len = 0;
  3252		unsigned char *pbuf = NULL;
  3253		struct ieee_param *param = NULL;
  3254		struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
  3255		struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  3256		struct sta_priv *pstapriv = &padapter->stapriv;
  3257	
  3258		param = (struct ieee_param *)rtw_malloc(wrqu->data.length);
  3259	
  3260		if (!param) {
  3261			DBG_88E(" rtw_set_beacon: ieee_param allocate fail !!!\n");
  3262	
  3263			return -ENOMEM;
  3264		}
  3265	
  3266		ret = get_private_handler_ieee_param(padapter, wrqu, param);
  3267	
  3268		if (ret != 0) {
  3269			kfree(param);
  3270			DBG_88E(" rtw_set_beacon: ieee_param get fail !!!\n");
  3271	
  3272			return ret;
  3273		}
  3274	
  3275		len = wrqu->data.length;
> 3276		pbuf = param->u.bcn_ie.buf;
  3277	
  3278		DBG_88E("%s, len =%d\n", __func__, len);
  3279	
  3280		if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
  3281			return -EINVAL;
  3282	
  3283		memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
  3284	
> 3285		if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
> 3286			pstapriv->max_num_sta = NUM_STA;
  3287	
> 3288		if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) == _SUCCESS) //  12 = Param header, 2 = Not packed.
  3289			ret = 0;
  3290		else
  3291			ret = -EINVAL;
  3292	
  3293		if (ret == 0 && (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)))
  3294			ret = -EFAULT;
  3295	
  3296		return ret;
  3297	}
  3298	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 41780 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3] staging: rtl8188eu: Fix private WEXT IOCTL calls
  2017-11-25 18:29 ` [PATCH v3] " ishraq.i.ashraf
  2017-11-25 21:25   ` Dan Carpenter
@ 2017-11-27 11:24   ` Johannes Berg
  2017-11-28  8:00   ` [PATCH] staging: rtl8188eu: fix kzalloc-simple.cocci warnings kbuild test robot
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 17+ messages in thread
From: Johannes Berg @ 2017-11-27 11:24 UTC (permalink / raw)
  To: ishraq.i.ashraf, gregkh
  Cc: himanshujha199640, goudapatilk, insafonov, dan.carpenter, devel,
	linux-kernel

In addition to what Dan said,


> +static iw_handler rtw_handlers_private[] = {
> +	NULL,                          /* Empty */
> +	rtw_hostapd_sta_flush_pvt,     /* RTL871X_HOSTAPD_FLUSH */
> +	rtw_add_sta_pvt,               /* RTL871X_HOSTAPD_ADD_STA */
> +	rtw_del_sta_pvt,               /* RTL871X_HOSTAPD_REMOVE_STA */
> +	rtw_ioctl_get_sta_data_pvt,    /* RTL871X_HOSTAPD_GET_INFO_STA */
> +	rtw_get_sta_wpaie_pvt,         /* RTL871X_HOSTAPD_GET_WPAIE_STA */
> +	rtw_set_encryption_pvt,        /* RTL871X_SET_ENCRYPTION */
> +	NULL,                          /* RTL871X_GET_ENCRYPTION */
> +	NULL,                          /* RTL871X_HOSTAPD_SET_FLAGS_STA */
> +	NULL,                          /* RTL871X_HOSTAPD_GET_RID */
> +	NULL,                          /* RTL871X_HOSTAPD_SET_RID */
> +	NULL,                          /* RTL871X_HOSTAPD_SET_ASSOC_AP_ADDR */
> +	NULL,                          /* RTL871X_HOSTAPD_SET_GENERIC_ELEMENT */
> +	NULL,                          /* RTL871X_HOSTAPD_MLME */
> +	NULL,                          /* RTL871X_HOSTAPD_SCAN_REQ */
> +	NULL,                          /* RTL871X_HOSTAPD_STA_CLEAR_STATS */
> +	rtw_set_beacon_pvt,            /* RTL871X_HOSTAPD_SET_BEACON */
> +	rtw_set_wps_beacon_pvt,        /* RTL871X_HOSTAPD_SET_WPS_BEACON */
> +	rtw_set_wps_probe_resp_pvt,    /* RTL871X_HOSTAPD_SET_WPS_PROBE_RESP */
> +	rtw_set_wps_assoc_resp_pvt,    /* RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP */
> +	rtw_set_hidden_ssid_pvt,       /* RTL871X_HOSTAPD_SET_HIDDEN_SSID */
> +	rtw_ioctl_set_macaddr_acl_pvt, /* RTL871X_HOSTAPD_SET_MACADDR_ACL */
> +	rtw_ioctl_acl_add_sta_pvt,     /* RTL871X_HOSTAPD_ACL_ADD_STA */
> +	rtw_ioctl_acl_remove_sta_pvt,  /* RTL871X_HOSTAPD_ACL_REMOVE_STA */
> +};
> 
You should probably use array element initializers:

static ... [] = {
	[RTL871X_HOSTAPD_FLUSH] = rtw_hostapd_sta_flush_pvt,
...
};

johannes

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/2] staging: rtl8188eu: Fix private WEXT IOCTL calls
  2017-11-26  0:45     ` Ishraq Ibne Ashraf
@ 2017-11-27 11:33       ` Johannes Berg
  0 siblings, 0 replies; 17+ messages in thread
From: Johannes Berg @ 2017-11-27 11:33 UTC (permalink / raw)
  To: Ishraq Ibne Ashraf, Dan Carpenter
  Cc: gregkh, himanshujha199640, goudapatilk, insafonov, devel, linux-kernel

Hi,

So I removed those call-through place because private wext operations
are a really bad idea and should just die. We don't want drivers to
require specially patched hostapd versions to work right, like here.

I suppose in staging you might want to work around that like here, but
that really means you see no future in mainline for this code, or
otherwise you should fix it the proper way.

johannes

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3] staging: rtl8188eu: Fix private WEXT IOCTL calls
  2017-11-25 18:29 ` [PATCH v3] " ishraq.i.ashraf
                     ` (2 preceding siblings ...)
  2017-11-28  8:00   ` [PATCH] staging: rtl8188eu: fix kzalloc-simple.cocci warnings kbuild test robot
@ 2017-11-28  8:00   ` kbuild test robot
  2017-12-04 15:20   ` kbuild test robot
  4 siblings, 0 replies; 17+ messages in thread
From: kbuild test robot @ 2017-11-28  8:00 UTC (permalink / raw)
  To: ishraq.i.ashraf
  Cc: kbuild-all, gregkh, himanshujha199640, goudapatilk, insafonov,
	dan.carpenter, devel, linux-kernel, johannes, Ishraq Ibne Ashraf

Hi Ishraq,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on staging/staging-testing]
[also build test WARNING on v4.15-rc1 next-20171127]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/ishraq-i-ashraf-gmail-com/staging-rtl8188eu-Fix-private-WEXT-IOCTL-calls/20171128-130403


coccinelle warnings: (new ones prefixed by >>)

>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3379:36-43: WARNING: kzalloc should be used for pwep, instead of kmalloc/memset

Please review and possibly fold the followup patch.

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH] staging: rtl8188eu: fix kzalloc-simple.cocci warnings
  2017-11-25 18:29 ` [PATCH v3] " ishraq.i.ashraf
  2017-11-25 21:25   ` Dan Carpenter
  2017-11-27 11:24   ` Johannes Berg
@ 2017-11-28  8:00   ` kbuild test robot
  2017-11-28  8:00   ` [PATCH v3] staging: rtl8188eu: Fix private WEXT IOCTL calls kbuild test robot
  2017-12-04 15:20   ` kbuild test robot
  4 siblings, 0 replies; 17+ messages in thread
From: kbuild test robot @ 2017-11-28  8:00 UTC (permalink / raw)
  To: ishraq.i.ashraf
  Cc: kbuild-all, gregkh, himanshujha199640, goudapatilk, insafonov,
	dan.carpenter, devel, linux-kernel, johannes, Ishraq Ibne Ashraf

drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3379:36-43: WARNING: kzalloc should be used for pwep, instead of kmalloc/memset


 Use kzalloc rather than kmalloc followed by memset with 0

 This considers some simple cases that are common and easy to validate
 Note in particular that there are no ...s in the rule, so all of the
 matched code has to be contiguous

Generated by: scripts/coccinelle/api/alloc/kzalloc-simple.cocci

Fixes: f1ac2c75e0c6 ("staging: rtl8188eu: Fix private WEXT IOCTL calls")
CC: Ishraq Ibne Ashraf <ishraq.i.ashraf@gmail.com>
Signed-off-by: Fengguang Wu <fengguang.wu@intel.com>
---

 ioctl_linux.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
@@ -3376,14 +3376,13 @@ static int rtw_set_encryption_pvt(struct
 			wep_key_len = wep_key_len <= 5 ? 5 : 13;
 			wep_total_len = wep_key_len + offsetof(struct ndis_802_11_wep, KeyMaterial);
 
-			pwep = (struct ndis_802_11_wep *)kmalloc(wep_total_len, GFP_KERNEL);
+			pwep = kzalloc(wep_total_len, GFP_KERNEL);
 			if (!pwep) {
 				DBG_88E(" r871x_set_encryption: pwep allocate fail !!!\n");
 				ret = -ENOMEM;
 				goto err_free_param;
 			}
 
-			memset(pwep, 0, wep_total_len);
 			pwep->KeyLength = wep_key_len;
 			pwep->Length = wep_total_len;
 		}

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3] staging: rtl8188eu: Fix private WEXT IOCTL calls
  2017-11-25 18:29 ` [PATCH v3] " ishraq.i.ashraf
                     ` (3 preceding siblings ...)
  2017-11-28  8:00   ` [PATCH v3] staging: rtl8188eu: Fix private WEXT IOCTL calls kbuild test robot
@ 2017-12-04 15:20   ` kbuild test robot
  4 siblings, 0 replies; 17+ messages in thread
From: kbuild test robot @ 2017-12-04 15:20 UTC (permalink / raw)
  To: ishraq.i.ashraf
  Cc: kbuild-all, gregkh, himanshujha199640, goudapatilk, insafonov,
	dan.carpenter, devel, linux-kernel, johannes, Ishraq Ibne Ashraf

[-- Attachment #1: Type: text/plain, Size: 24010 bytes --]

Hi Ishraq,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on staging/staging-testing]
[also build test ERROR on v4.15-rc2 next-20171204]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/ishraq-i-ashraf-gmail-com/staging-rtl8188eu-Fix-private-WEXT-IOCTL-calls/20171128-130403
config: x86_64-randconfig-u0-12042048 (attached as .config)
compiler: gcc-5 (Debian 5.5.0-3) 5.4.1 20171010
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_hostapd_sta_flush_pvt':
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3088:9: error: implicit declaration of function 'rtw_sta_flush' [-Werror=implicit-function-declaration]
     return rtw_sta_flush(padapter);
            ^
   In file included from include/linux/kernel.h:14:0,
                    from include/linux/skbuff.h:17,
                    from include/linux/if_ether.h:23,
                    from include/linux/ieee80211.h:21,
                    from drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:17:
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_add_sta_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3113:11: error: 'union <anonymous>' has no member named 'add_sta'
      param->u.add_sta.aid,
              ^
   include/linux/printk.h:308:34: note: in definition of macro 'pr_info'
     printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
                                     ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3112:2: note: in expansion of macro 'DBG_88E'
     DBG_88E("rtw_add_sta(aid =%d) =%pM\n",
     ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3134:18: error: 'union <anonymous>' has no member named 'add_sta'
     flags = param->u.add_sta.flags;
                     ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3135:22: error: 'union <anonymous>' has no member named 'add_sta'
     psta->aid = param->u.add_sta.aid; /* aid = 1~2007. */
                         ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3137:35: error: 'union <anonymous>' has no member named 'add_sta'
     memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
                                      ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3140:6: error: 'WLAN_STA_WME' undeclared (first use in this function)
     if (WLAN_STA_WME&flags)
         ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3140:6: note: each undeclared identifier is reported only once for each function it appears in
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3149:6: error: 'WLAN_STA_HT' undeclared (first use in this function)
     if (WLAN_STA_HT&flags) {
         ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3153:19: error: 'union <anonymous>' has no member named 'add_sta'
             &param->u.add_sta.ht_cap,
                      ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3162:2: error: implicit declaration of function 'update_sta_info_apmode' [-Werror=implicit-function-declaration]
     update_sta_info_apmode(padapter, psta);
     ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_del_sta_pvt':
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3225:11: error: 'struct sta_priv' has no member named 'asoc_list_cnt'
      pstapriv->asoc_list_cnt--;
              ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3226:13: error: implicit declaration of function 'ap_free_sta' [-Werror=implicit-function-declaration]
      updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
                ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3230:2: error: implicit declaration of function 'associated_clients_update' [-Werror=implicit-function-declaration]
     associated_clients_update(padapter, updated);
     ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_set_beacon_pvt':
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3267:17: error: 'union <anonymous>' has no member named 'bcn_ie'
     pbuf = param->u.bcn_ie.buf;
                    ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3276:18: error: 'struct sta_priv' has no member named 'max_num_sta'
     memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
                     ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3276:41: error: 'union <anonymous>' has no member named 'bcn_ie'
     memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
                                            ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3278:15: error: 'struct sta_priv' has no member named 'max_num_sta'
     if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
                  ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3278:52: error: 'struct sta_priv' has no member named 'max_num_sta'
     if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
                                                       ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3279:11: error: 'struct sta_priv' has no member named 'max_num_sta'
      pstapriv->max_num_sta = NUM_STA;
              ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3281:6: error: implicit declaration of function 'rtw_check_beacon_data' [-Werror=implicit-function-declaration]
     if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) != _SUCCESS) { /*  12 = Param header, 2 = Not packed. */
         ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_set_encryption_pvt':
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3411:4: error: implicit declaration of function 'set_wep_key' [-Werror=implicit-function-declaration]
       set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
       ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3477:4: error: implicit declaration of function 'set_group_key' [-Werror=implicit-function-declaration]
       set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
       ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3521:5: error: implicit declaration of function 'set_pairwise_key' [-Werror=implicit-function-declaration]
        set_pairwise_key(padapter, psta);
        ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_get_sta_wpaie_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3624:10: error: 'struct sta_info' has no member named 'wpa_ie'
     if (psta->wpa_ie[0] == WLAN_EID_RSN ||
             ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3625:10: error: 'struct sta_info' has no member named 'wpa_ie'
         psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
             ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3629:20: error: 'struct sta_info' has no member named 'wpa_ie'
      wpa_ie_len = psta->wpa_ie[1];
                       ^
   In file included from include/linux/skbuff.h:17:0,
                    from include/linux/if_ether.h:23,
                    from include/linux/ieee80211.h:21,
                    from drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:17:
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3630:52: error: 'struct sta_info' has no member named 'wpa_ie'
      copy_len = min_t(int, wpa_ie_len + 2, sizeof(psta->wpa_ie));
                                                       ^
   include/linux/kernel.h:791:13: note: in definition of macro '__min'
     t2 min2 = (y);     \
                ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3630:14: note: in expansion of macro 'min_t'
      copy_len = min_t(int, wpa_ie_len + 2, sizeof(psta->wpa_ie));
                 ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3632:40: error: 'struct sta_info' has no member named 'wpa_ie'
      memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
                                           ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_set_wps_beacon_pvt':
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3681:17: error: 'struct mlme_priv' has no member named 'wps_beacon_ie'
     kfree(pmlmepriv->wps_beacon_ie);
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3682:11: error: 'struct mlme_priv' has no member named 'wps_beacon_ie'
     pmlmepriv->wps_beacon_ie = NULL;
              ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3686:12: error: 'struct mlme_priv' has no member named 'wps_beacon_ie'
      pmlmepriv->wps_beacon_ie = kmalloc(ie_len, GFP_KERNEL);
               ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3687:17: error: 'struct mlme_priv' has no member named 'wps_beacon_ie'
      if (!pmlmepriv->wps_beacon_ie) {
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3693:12: error: 'struct mlme_priv' has no member named 'wps_beacon_ie_len'
      pmlmepriv->wps_beacon_ie_len = ie_len;
               ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3694:19: error: 'struct mlme_priv' has no member named 'wps_beacon_ie'
      memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
                      ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3694:44: error: 'union <anonymous>' has no member named 'bcn_ie'
      memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
                                               ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3695:3: error: implicit declaration of function 'update_beacon' [-Werror=implicit-function-declaration]
      update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
      ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3696:11: error: 'struct mlme_ext_priv' has no member named 'bstart_bss'
      pmlmeext->bstart_bss = true;
              ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3704:17: error: 'struct mlme_priv' has no member named 'wps_beacon_ie'
     kfree(pmlmepriv->wps_beacon_ie);
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3709:17: error: 'struct mlme_priv' has no member named 'wps_beacon_ie'
     kfree(pmlmepriv->wps_beacon_ie);
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_set_wps_probe_resp_pvt':
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3745:17: error: 'struct mlme_priv' has no member named 'wps_probe_resp_ie'
     kfree(pmlmepriv->wps_probe_resp_ie);
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3746:11: error: 'struct mlme_priv' has no member named 'wps_probe_resp_ie'
     pmlmepriv->wps_probe_resp_ie = NULL;
              ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3750:12: error: 'struct mlme_priv' has no member named 'wps_probe_resp_ie'
      pmlmepriv->wps_probe_resp_ie = kmalloc(ie_len, GFP_KERNEL);
               ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3751:17: error: 'struct mlme_priv' has no member named 'wps_probe_resp_ie'
      if (!pmlmepriv->wps_probe_resp_ie) {
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3757:12: error: 'struct mlme_priv' has no member named 'wps_probe_resp_ie_len'
      pmlmepriv->wps_probe_resp_ie_len = ie_len;
               ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3758:19: error: 'struct mlme_priv' has no member named 'wps_probe_resp_ie'
      memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
                      ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3758:48: error: 'union <anonymous>' has no member named 'bcn_ie'
      memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
                                                   ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3766:17: error: 'struct mlme_priv' has no member named 'wps_probe_resp_ie'
     kfree(pmlmepriv->wps_probe_resp_ie);
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3771:17: error: 'struct mlme_priv' has no member named 'wps_probe_resp_ie'
     kfree(pmlmepriv->wps_probe_resp_ie);
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_set_wps_assoc_resp_pvt':
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3807:17: error: 'struct mlme_priv' has no member named 'wps_assoc_resp_ie'
     kfree(pmlmepriv->wps_assoc_resp_ie);
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3808:11: error: 'struct mlme_priv' has no member named 'wps_assoc_resp_ie'
     pmlmepriv->wps_assoc_resp_ie = NULL;
              ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3812:12: error: 'struct mlme_priv' has no member named 'wps_assoc_resp_ie'
      pmlmepriv->wps_assoc_resp_ie = kmalloc(ie_len, GFP_KERNEL);
               ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3813:17: error: 'struct mlme_priv' has no member named 'wps_assoc_resp_ie'
      if (!pmlmepriv->wps_assoc_resp_ie) {
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3819:12: error: 'struct mlme_priv' has no member named 'wps_assoc_resp_ie_len'
      pmlmepriv->wps_assoc_resp_ie_len = ie_len;
               ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3820:19: error: 'struct mlme_priv' has no member named 'wps_assoc_resp_ie'
      memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
                      ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3820:48: error: 'union <anonymous>' has no member named 'bcn_ie'
      memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
                                                   ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3828:17: error: 'struct mlme_priv' has no member named 'wps_assoc_resp_ie'
     kfree(pmlmepriv->wps_assoc_resp_ie);
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3833:17: error: 'struct mlme_priv' has no member named 'wps_assoc_resp_ie'
     kfree(pmlmepriv->wps_assoc_resp_ie);
                    ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_ioctl_get_sta_data_pvt':
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3913:41: error: dereferencing pointer to incomplete type 'struct ieee_param_ex'
     psta_data = (struct sta_data *)param_ex->data;
                                            ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3935:11: error: dereferencing pointer to incomplete type 'struct sta_data'
     psta_data->aid = (u16)psta->aid;
              ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3936:30: error: 'struct sta_info' has no member named 'capability'
     psta_data->capability = psta->capability;
                                 ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3937:25: error: 'struct sta_info' has no member named 'flags'
     psta_data->flags = psta->flags;
                            ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3949:9: error: 'struct sta_info' has no member named 'nonerp_set'
      ((psta->nonerp_set) |
            ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3950:8: error: 'struct sta_info' has no member named 'no_short_slot_time_set'
      (psta->no_short_slot_time_set << 1) |
           ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3951:8: error: 'struct sta_info' has no member named 'no_short_preamble_set'
      (psta->no_short_preamble_set << 2) |
           ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3952:8: error: 'struct sta_info' has no member named 'no_ht_gf_set'
      (psta->no_ht_gf_set << 3) |
           ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3953:8: error: 'struct sta_info' has no member named 'no_ht_set'
      (psta->no_ht_set << 4) |
           ^
>> drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:3954:8: error: 'struct sta_info' has no member named 'ht_20mhz_set'
      (psta->ht_20mhz_set << 5));
           ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_ioctl_set_macaddr_acl_pvt':
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:4003:2: error: implicit declaration of function 'rtw_set_macaddr_acl' [-Werror=implicit-function-declaration]
     rtw_set_macaddr_acl(padapter, param->u.mlme.command);
     ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_ioctl_acl_add_sta_pvt':
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:4048:8: error: implicit declaration of function 'rtw_acl_add_sta' [-Werror=implicit-function-declaration]
     ret = rtw_acl_add_sta(padapter, param->sta_addr);
           ^
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'rtw_ioctl_acl_remove_sta_pvt':
   drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:4095:8: error: implicit declaration of function 'rtw_acl_remove_sta' [-Werror=implicit-function-declaration]
     ret = rtw_acl_remove_sta(padapter, param->sta_addr);
           ^
   cc1: some warnings being treated as errors

vim +3113 drivers/staging/rtl8188eu/os_dep/ioctl_linux.c

  3080	
  3081	static int rtw_hostapd_sta_flush_pvt(struct net_device *dev,
  3082					     struct iw_request_info *info,
  3083					     union iwreq_data *wrqu,
  3084					     char *extra)
  3085	{
  3086		struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
  3087		flush_all_cam_entry(padapter); /* Clear CAM. */
> 3088		return rtw_sta_flush(padapter);
  3089	}
  3090	
  3091	static int rtw_add_sta_pvt(struct net_device *dev,
  3092				   struct iw_request_info *info,
  3093				   union iwreq_data *wrqu,
  3094				   char *extra)
  3095	{
  3096		int ret;
  3097		int flags;
  3098		struct sta_info *psta;
  3099		struct ieee_param *param;
  3100		struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
  3101		struct sta_priv *pstapriv = &padapter->stapriv;
  3102		struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  3103	
  3104		param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
  3105		if (!param)
  3106			return -ENOMEM;
  3107	
  3108		ret = get_private_handler_ieee_param(padapter, wrqu, param);
  3109		if (ret)
  3110			goto err_free_param;
  3111	
  3112		DBG_88E("rtw_add_sta(aid =%d) =%pM\n",
> 3113			param->u.add_sta.aid,
  3114			(param->sta_addr));
  3115	
  3116		if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE))) {
  3117			ret = -EINVAL;
  3118			goto err_free_param;
  3119		}
  3120	
  3121		if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
  3122		    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
  3123		    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
  3124			ret = -EINVAL;
  3125			goto err_free_param;
  3126		}
  3127	
  3128		psta = rtw_get_stainfo(pstapriv, param->sta_addr);
  3129		if (!psta) {
  3130			ret = -ENOMEM;
  3131			goto err_free_param;
  3132		}
  3133	
  3134		flags = param->u.add_sta.flags;
  3135		psta->aid = param->u.add_sta.aid; /* aid = 1~2007. */
  3136	
  3137		memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
  3138	
  3139		/* Check WMM cap. */
  3140		if (WLAN_STA_WME&flags)
  3141			psta->qos_option = 1;
  3142		else
  3143			psta->qos_option = 0;
  3144	
  3145		if (pmlmepriv->qospriv.qos_option == 0)
  3146			psta->qos_option = 0;
  3147	
  3148		/* Check 802.11n HT cap. */
  3149		if (WLAN_STA_HT&flags) {
  3150			psta->htpriv.ht_option = true;
  3151			psta->qos_option = 1;
  3152			memcpy(&psta->htpriv.ht_cap,
  3153			       &param->u.add_sta.ht_cap,
  3154			       sizeof(struct ieee80211_ht_cap));
  3155		} else {
  3156			psta->htpriv.ht_option = false;
  3157		}
  3158	
  3159		if (pmlmepriv->htpriv.ht_option == false)
  3160			psta->htpriv.ht_option = false;
  3161	
  3162		update_sta_info_apmode(padapter, psta);
  3163	
  3164		if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
  3165			ret = -EFAULT;
  3166			goto err_free_param;
  3167		}
  3168	
  3169		kfree(param);
  3170		return 0;
  3171	
  3172	err_free_param:
  3173		kfree(param);
  3174		return ret;
  3175	}
  3176	
  3177	static int rtw_del_sta_pvt(struct net_device *dev,
  3178				   struct iw_request_info *info,
  3179				   union iwreq_data *wrqu,
  3180				   char *extra)
  3181	{
  3182		int ret;
  3183		int updated;
  3184		struct sta_info *psta;
  3185		struct ieee_param *param;
  3186		struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
  3187		struct sta_priv *pstapriv = &padapter->stapriv;
  3188		struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  3189	
  3190		param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
  3191		if (!param)
  3192			return -ENOMEM;
  3193	
  3194		ret = get_private_handler_ieee_param(padapter, wrqu, param);
  3195		if (ret)
  3196			goto err_free_param;
  3197	
  3198		DBG_88E("rtw_del_sta =%pM\n", (param->sta_addr));
  3199	
  3200		if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) {
  3201			ret = -EINVAL;
  3202			goto err_free_param;
  3203		}
  3204	
  3205		if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
  3206		    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
  3207		    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
  3208			ret = -EINVAL;
  3209			goto err_free_param;
  3210		}
  3211	
  3212		psta = rtw_get_stainfo(pstapriv, param->sta_addr);
  3213		if (!psta) {
  3214			DBG_88E("rtw_del_sta(), sta has already been removed or never been added\n");
  3215			ret = -ENOMEM;
  3216			goto err_free_param;
  3217		}
  3218	
  3219		spin_lock_bh(&pstapriv->asoc_list_lock);
  3220	
  3221		updated = 0;
  3222	
  3223		if (!list_empty(&psta->asoc_list)) {
  3224			list_del_init(&psta->asoc_list);
> 3225			pstapriv->asoc_list_cnt--;
  3226			updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
  3227		}
  3228	
  3229		spin_unlock_bh(&pstapriv->asoc_list_lock);
> 3230		associated_clients_update(padapter, updated);
  3231	
  3232		if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
  3233			ret = -EFAULT;
  3234			goto err_free_param;
  3235		}
  3236	
  3237		kfree(param);
  3238		return 0;
  3239	
  3240	err_free_param:
  3241		kfree(param);
  3242		return ret;
  3243	}
  3244	
  3245	static int rtw_set_beacon_pvt(struct net_device *dev,
  3246				      struct iw_request_info *info,
  3247				      union iwreq_data *wrqu,
  3248				      char *extra)
  3249	{
  3250		int ret;
  3251		int len;
  3252		unsigned char *pbuf;
  3253		struct ieee_param *param;
  3254		struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
  3255		struct sta_priv *pstapriv = &padapter->stapriv;
  3256		struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  3257	
  3258		param = (struct ieee_param *)kmalloc(wrqu->data.length, GFP_KERNEL);
  3259		if (!param)
  3260			return -ENOMEM;
  3261	
  3262		ret = get_private_handler_ieee_param(padapter, wrqu, param);
  3263		if (ret)
  3264			goto err_free_param;
  3265	
  3266		len = wrqu->data.length;
  3267		pbuf = param->u.bcn_ie.buf;
  3268	
  3269		DBG_88E("%s, len =%d\n", __func__, len);
  3270	
  3271		if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) {
  3272			ret = -EINVAL;
  3273			goto err_free_param;
  3274		}
  3275	
> 3276		memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
  3277	
  3278		if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
  3279			pstapriv->max_num_sta = NUM_STA;
  3280	
  3281		if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) != _SUCCESS) { /*  12 = Param header, 2 = Not packed. */
  3282			ret = -EINVAL;
  3283			goto err_free_param;
  3284		}
  3285	
  3286		if (copy_to_user(wrqu->data.pointer, param, wrqu->data.length)) {
  3287			ret = -EFAULT;
  3288			goto err_free_param;
  3289		}
  3290	
  3291		kfree(param);
  3292		return 0;
  3293	
  3294	err_free_param:
  3295		kfree(param);
  3296		return ret;
  3297	}
  3298	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 31164 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2017-12-04 15:20 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-23  1:29 [PATCH] staging: rtl8188eu: Fix private WEXT IOCTL calls ishraq.i.ashraf
2017-11-23 13:24 ` Dan Carpenter
2017-11-25  0:52 ` [PATCH 2/2] " ishraq.i.ashraf
2017-11-25  4:40   ` Dan Carpenter
2017-11-25 18:12     ` Ishraq Ibne Ashraf
2017-11-26  0:45     ` Ishraq Ibne Ashraf
2017-11-27 11:33       ` Johannes Berg
2017-11-25  1:29 ` [PATCH v2] " ishraq.i.ashraf
2017-11-25  4:55   ` Dan Carpenter
2017-11-25 18:29 ` [PATCH v3] " ishraq.i.ashraf
2017-11-25 21:25   ` Dan Carpenter
2017-11-27 11:24   ` Johannes Berg
2017-11-28  8:00   ` [PATCH] staging: rtl8188eu: fix kzalloc-simple.cocci warnings kbuild test robot
2017-11-28  8:00   ` [PATCH v3] staging: rtl8188eu: Fix private WEXT IOCTL calls kbuild test robot
2017-12-04 15:20   ` kbuild test robot
2017-11-26 20:45 ` [PATCH] " kbuild test robot
2017-11-26 23:20 ` kbuild test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.