diff options
Diffstat (limited to '')
-rw-r--r-- | drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c | 1105 |
1 files changed, 508 insertions, 597 deletions
diff --git a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c index f0839f6a9345..93dc844a10b3 100644 --- a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c @@ -16,7 +16,6 @@ #include <osdep_service.h> #include <drv_types.h> -#include <rtw_ioctl_set.h> #include <xmit_osdep.h> #include "ioctl_cfg80211.h" @@ -26,8 +25,6 @@ #define RTW_MAX_REMAIN_ON_CHANNEL_DURATION 65535 /* ms */ #define RTW_MAX_NUM_PMKIDS 4 -#define RTW_CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ - static const u32 rtw_cipher_suites[] = { WLAN_CIPHER_SUITE_WEP40, WLAN_CIPHER_SUITE_WEP104, @@ -242,37 +239,21 @@ rtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { }, }; -#define MAX_BSSINFO_LEN 1000 static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter, struct wlan_network *pnetwork) { int ret = 0; struct ieee80211_channel *notify_channel; struct cfg80211_bss *bss; - /* struct ieee80211_supported_band *band; */ u16 channel; u32 freq; - u64 notify_timestamp; - u16 notify_capability; - u16 notify_interval; u8 *notify_ie; size_t notify_ielen; s32 notify_signal; - u8 buf[MAX_BSSINFO_LEN], *pbuf; - size_t len; - struct ieee80211_hdr *pwlanhdr; struct wireless_dev *wdev = padapter->rtw_wdev; struct wiphy *wiphy = wdev->wiphy; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - /* DBG_8723A("%s\n", __func__); */ - - if (pnetwork->network.IELength > MAX_IE_SZ) { - DBG_8723A("%s IE Length too long > %d byte\n", __func__, - MAX_IE_SZ); - goto exit; - } - channel = pnetwork->network.DSConfig; if (channel <= RTW_CH_MAX_2G_CHANNEL) freq = ieee80211_channel_to_frequency(channel, @@ -283,17 +264,8 @@ static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter, notify_channel = ieee80211_get_channel(wiphy, freq); - notify_timestamp = jiffies_to_msecs(jiffies) * 1000; /* uSec */ - - notify_interval = - get_unaligned_le16( - rtw_get_beacon_interval23a_from_ie(pnetwork->network.IEs)); - notify_capability = - get_unaligned_le16( - rtw_get_capability23a_from_ie(pnetwork->network.IEs)); - - notify_ie = pnetwork->network.IEs + _FIXED_IE_LENGTH_; - notify_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_; + notify_ie = pnetwork->network.IEs; + notify_ielen = pnetwork->network.IELength; /* We've set wiphy's signal_type as CFG80211_SIGNAL_TYPE_MBM: * signal strength in mBm (100*dBm) @@ -305,35 +277,14 @@ static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter, } else { notify_signal = 100 * translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength); /* dbm */ } - pbuf = buf; - - pwlanhdr = (struct ieee80211_hdr *)pbuf; - - pwlanhdr->seq_ctrl = 0; - - if (pnetwork->network.reserved == 1) { /* WIFI_BEACON */ - eth_broadcast_addr(pwlanhdr->addr1); - pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_BEACON); - } else { - ether_addr_copy(pwlanhdr->addr1, myid(&padapter->eeprompriv)); - pwlanhdr->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_PROBE_RESP); - } - - ether_addr_copy(pwlanhdr->addr2, pnetwork->network.MacAddress); - ether_addr_copy(pwlanhdr->addr3, pnetwork->network.MacAddress); - pbuf += sizeof(struct ieee80211_hdr_3addr); - len = sizeof(struct ieee80211_hdr_3addr); - - memcpy(pbuf, pnetwork->network.IEs, pnetwork->network.IELength); - len += pnetwork->network.IELength; - - bss = cfg80211_inform_bss_frame(wiphy, notify_channel, - (struct ieee80211_mgmt *)buf, len, - notify_signal, GFP_ATOMIC); + bss = cfg80211_inform_bss(wiphy, notify_channel, + pnetwork->network.MacAddress, + pnetwork->network.tsf, + pnetwork->network.capability, + pnetwork->network.beacon_interval, + notify_ie, notify_ielen, + notify_signal, GFP_ATOMIC); if (unlikely(!bss)) { DBG_8723A("rtw_cfg80211_inform_bss error\n"); @@ -342,7 +293,6 @@ static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter, cfg80211_put_bss(wiphy, bss); -exit: return ret; } @@ -467,10 +417,9 @@ exit: return res; } -static int set_group_key(struct rtw_adapter *padapter, u8 *key, u32 alg, - u8 keyid) +static int set_group_key(struct rtw_adapter *padapter, struct key_params *parms, + u32 alg, u8 keyid) { - u8 keylen; struct cmd_obj *pcmd; struct setkey_parm *psetkeyparm; struct cmd_priv *pcmdpriv = &padapter->cmdpriv; @@ -503,20 +452,7 @@ static int set_group_key(struct rtw_adapter *padapter, u8 *key, u32 alg, psetkeyparm->set_tx = 1; - switch (alg) { - case WLAN_CIPHER_SUITE_WEP40: - keylen = 5; - break; - case WLAN_CIPHER_SUITE_WEP104: - keylen = 13; - break; - case WLAN_CIPHER_SUITE_TKIP: - case WLAN_CIPHER_SUITE_CCMP: - default: - keylen = 16; - } - - memcpy(&psetkeyparm->key[0], key, keylen); + memcpy(&psetkeyparm->key, parms->key, parms->key_len); pcmd->cmdcode = _SetKey_CMD_; pcmd->parmbuf = (u8 *) psetkeyparm; @@ -530,58 +466,21 @@ exit: return res; } -static int set_wep_key(struct rtw_adapter *padapter, u8 *key, u16 keylen, - u8 keyid) -{ - u32 alg; - - switch (keylen) { - case 5: - alg = WLAN_CIPHER_SUITE_WEP40; - break; - case 13: - alg = WLAN_CIPHER_SUITE_WEP104; - break; - default: - alg = 0; - } - - return set_group_key(padapter, key, alg, keyid); -} - -static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, - struct ieee_param *param, - u32 param_len) +static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, u8 key_index, + int set_tx, const u8 *sta_addr, + struct key_params *keyparms) { int ret = 0; - u16 wep_key_len; - u8 wep_key_idx; + int key_len; struct sta_info *psta = NULL, *pbcmc_sta = NULL; struct rtw_adapter *padapter = netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct security_priv *psecuritypriv = &padapter->securitypriv; struct sta_priv *pstapriv = &padapter->stapriv; DBG_8723A("%s\n", __func__); - param->u.crypt.err = 0; - param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0'; - - /* sizeof(struct ieee_param) = 64 bytes; */ - /* if (param_len != (u32) ((u8 *) param->u.crypt.key - - (u8 *) param) + param->u.crypt.key_len) */ - if (param_len != sizeof(struct ieee_param) + param->u.crypt.key_len) { - ret = -EINVAL; - goto exit; - } - - if (is_broadcast_ether_addr(param->sta_addr)) { - if (param->u.crypt.idx >= WEP_KEYS) { - ret = -EINVAL; - goto exit; - } - } else { - psta = rtw_get_stainfo23a(pstapriv, param->sta_addr); + if (!is_broadcast_ether_addr(sta_addr)) { + psta = rtw_get_stainfo23a(pstapriv, sta_addr); if (!psta) { /* ret = -EINVAL; */ DBG_8723A("rtw_set_encryption(), sta has already " @@ -590,32 +489,14 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, } } - if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) { - /* todo:clear default encryption keys */ - - DBG_8723A("clear default encryption keys, keyid =%d\n", - param->u.crypt.idx); - - goto exit; - } + key_len = keyparms->key_len; - if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) { + if (!psta && (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 || + keyparms->cipher == WLAN_CIPHER_SUITE_WEP104)) { DBG_8723A("r871x_set_encryption, crypt.alg = WEP\n"); - wep_key_idx = param->u.crypt.idx; - wep_key_len = param->u.crypt.key_len; - DBG_8723A("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; - } + key_index, key_len); if (psecuritypriv->bWepDefaultKeyIdxSet == 0) { /* wep default key has not been set, so use @@ -623,100 +504,84 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled; - psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40; - psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40; + psecuritypriv->dot11PrivacyAlgrthm = keyparms->cipher; + psecuritypriv->dot118021XGrpPrivacy = keyparms->cipher; - if (wep_key_len == 13) { - psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104; - psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP104; - } - - psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx; + psecuritypriv->dot11PrivacyKeyIndex = key_index; } - memcpy(&psecuritypriv->wep_key[wep_key_idx].key, - param->u.crypt.key, wep_key_len); + memcpy(&psecuritypriv->wep_key[key_index].key, + keyparms->key, key_len); - psecuritypriv->wep_key[wep_key_idx].keylen = wep_key_len; + psecuritypriv->wep_key[key_index].keylen = key_len; - set_wep_key(padapter, param->u.crypt.key, wep_key_len, - wep_key_idx); + set_group_key(padapter, keyparms, keyparms->cipher, key_index); goto exit; - } - if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /* group key */ - if (param->u.crypt.set_tx == 0) { /* group key */ - if (strcmp(param->u.crypt.alg, "WEP") == 0) { + if (!psta) { /* group key */ + if (set_tx == 0) { /* group key */ + if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 || + keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) { DBG_8723A("%s, set group_key, WEP\n", __func__); memcpy(psecuritypriv-> - dot118021XGrpKey[param->u.crypt.idx]. - skey, param->u.crypt.key, - (param->u.crypt.key_len > - 16 ? 16 : param->u.crypt.key_len)); - - psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40; - if (param->u.crypt.key_len == 13) { - psecuritypriv->dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_WEP104; - } + dot118021XGrpKey[key_index].skey, + keyparms->key, key_len); - } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { + psecuritypriv->dot118021XGrpPrivacy = + keyparms->cipher; + } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) { DBG_8723A("%s, set group_key, TKIP\n", __func__); - psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_TKIP; + psecuritypriv->dot118021XGrpPrivacy = + WLAN_CIPHER_SUITE_TKIP; memcpy(psecuritypriv-> - dot118021XGrpKey[param->u.crypt.idx]. - skey, param->u.crypt.key, - (param->u.crypt.key_len > - 16 ? 16 : param->u.crypt.key_len)); + dot118021XGrpKey[key_index].skey, + keyparms->key, + (key_len > 16 ? 16 : key_len)); - /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */ /* set mic key */ memcpy(psecuritypriv-> - dot118021XGrptxmickey[param->u.crypt. - idx].skey, - ¶m->u.crypt.key[16], 8); + dot118021XGrptxmickey[key_index].skey, + &keyparms->key[16], 8); memcpy(psecuritypriv-> - dot118021XGrprxmickey[param->u.crypt. - idx].skey, - ¶m->u.crypt.key[24], 8); + dot118021XGrprxmickey[key_index].skey, + &keyparms->key[24], 8); psecuritypriv->busetkipkey = 1; - } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) { - DBG_8723A("%s, set group_key, CCMP\n", + } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) { + DBG_8723A("%s, set group_key, CCMP\n", __func__); - psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_CCMP; + psecuritypriv->dot118021XGrpPrivacy = + WLAN_CIPHER_SUITE_CCMP; memcpy(psecuritypriv-> - dot118021XGrpKey[param->u.crypt.idx]. - skey, param->u.crypt.key, - (param->u.crypt.key_len > - 16 ? 16 : param->u.crypt.key_len)); + dot118021XGrpKey[key_index].skey, + keyparms->key, + (key_len > 16 ? 16 : key_len)); } else { DBG_8723A("%s, set group_key, none\n", __func__); - psecuritypriv->dot118021XGrpPrivacy = - 0; + psecuritypriv->dot118021XGrpPrivacy = 0; } - psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx; + psecuritypriv->dot118021XGrpKeyid = key_index; psecuritypriv->binstallGrpkey = 1; psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy; - set_group_key(padapter, param->u.crypt.key, + set_group_key(padapter, keyparms, psecuritypriv->dot118021XGrpPrivacy, - param->u.crypt.idx); + key_index); pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter); if (pbcmc_sta) { @@ -732,140 +597,110 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, 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) { - /* pairwise key */ - memcpy(psta->dot118021x_UncstKey.skey, - param->u.crypt.key, - (param->u.crypt.key_len > - 16 ? 16 : param->u.crypt.key_len)); + if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { + /* psk/802_1x */ + if (set_tx == 1) { + /* pairwise key */ + memcpy(psta->dot118021x_UncstKey.skey, + keyparms->key, (key_len > 16 ? 16 : key_len)); - if (!strcmp(param->u.crypt.alg, "WEP")) { - DBG_8723A("%s, set pairwise key, WEP\n", - __func__); + if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 || + keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) { + DBG_8723A("%s, set pairwise key, WEP\n", + __func__); - psta->dot118021XPrivacy = WLAN_CIPHER_SUITE_WEP40; - if (param->u.crypt.key_len == 13) { - psta->dot118021XPrivacy = - WLAN_CIPHER_SUITE_WEP104; - } - } else if (!strcmp(param->u.crypt.alg, "TKIP")) { - DBG_8723A("%s, set pairwise key, " - "TKIP\n", __func__); + psecuritypriv->dot118021XGrpPrivacy = + keyparms->cipher; + } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) { + DBG_8723A("%s, set pairwise key, TKIP\n", + __func__); - psta->dot118021XPrivacy = WLAN_CIPHER_SUITE_TKIP; + psta->dot118021XPrivacy = + WLAN_CIPHER_SUITE_TKIP; - /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */ - /* set mic key */ - memcpy(psta->dot11tkiptxmickey.skey, - ¶m->u.crypt.key[16], 8); - memcpy(psta->dot11tkiprxmickey.skey, - ¶m->u.crypt.key[24], 8); + /* set mic key */ + memcpy(psta->dot11tkiptxmickey.skey, + &keyparms->key[16], 8); + memcpy(psta->dot11tkiprxmickey.skey, + &keyparms->key[24], 8); - psecuritypriv->busetkipkey = 1; + psecuritypriv->busetkipkey = 1; - } else if (!strcmp(param->u.crypt.alg, "CCMP")) { + } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) { + DBG_8723A("%s, set pairwise key, CCMP\n", + __func__); - DBG_8723A("%s, set pairwise key, " - "CCMP\n", __func__); + psta->dot118021XPrivacy = + WLAN_CIPHER_SUITE_CCMP; + } else { + DBG_8723A("%s, set pairwise key, none\n", + __func__); - psta->dot118021XPrivacy = WLAN_CIPHER_SUITE_CCMP; - } else { - DBG_8723A("%s, set pairwise key, " - "none\n", __func__); + psta->dot118021XPrivacy = 0; + } - psta->dot118021XPrivacy = 0; - } + set_pairwise_key(padapter, psta); - set_pairwise_key(padapter, psta); - - psta->ieee8021x_blocked = false; - - psta->bpairwise_key_installed = true; - } else { /* group key??? */ - if (!strcmp(param->u.crypt.alg, "WEP")) { - memcpy(psecuritypriv-> - dot118021XGrpKey[param->u.crypt. - idx].skey, - param->u.crypt.key, - (param->u.crypt.key_len > - 16 ? 16 : param->u.crypt. - key_len)); - - psecuritypriv->dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_WEP40; - if (param->u.crypt.key_len == 13) { - psecuritypriv-> - dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_WEP104; - } - } else if (!strcmp(param->u.crypt.alg, "TKIP")) { - psecuritypriv->dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_TKIP; - - memcpy(psecuritypriv-> - dot118021XGrpKey[param->u.crypt. - idx].skey, - param->u.crypt.key, - (param->u.crypt.key_len > - 16 ? 16 : param->u.crypt. - key_len)); - - /* DEBUG_ERR("set key length :param->u" - ".crypt.key_len =%d\n", - param->u.crypt.key_len); */ - /* set mic key */ - memcpy(psecuritypriv-> - dot118021XGrptxmickey[param->u. - crypt.idx]. - skey, ¶m->u.crypt.key[16], - 8); - memcpy(psecuritypriv-> - dot118021XGrprxmickey[param->u. - crypt.idx]. - skey, ¶m->u.crypt.key[24], - 8); - - psecuritypriv->busetkipkey = 1; - - } else if (!strcmp(param->u.crypt.alg, "CCMP")) { - psecuritypriv->dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_CCMP; - - memcpy(psecuritypriv-> - dot118021XGrpKey[param->u.crypt. - idx].skey, - param->u.crypt.key, - (param->u.crypt.key_len > - 16 ? 16 : param->u.crypt. - key_len)); - } else { - psecuritypriv->dot118021XGrpPrivacy = - 0; - } + psta->ieee8021x_blocked = false; - psecuritypriv->dot118021XGrpKeyid = - param->u.crypt.idx; + psta->bpairwise_key_installed = true; + } else { /* group key??? */ + if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 || + keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) { + memcpy(psecuritypriv-> + dot118021XGrpKey[key_index].skey, + keyparms->key, key_len); - psecuritypriv->binstallGrpkey = 1; + psecuritypriv->dot118021XGrpPrivacy = + keyparms->cipher; + } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) { + psecuritypriv->dot118021XGrpPrivacy = + WLAN_CIPHER_SUITE_TKIP; - psecuritypriv->dot11PrivacyAlgrthm = - psecuritypriv->dot118021XGrpPrivacy; + memcpy(psecuritypriv-> + dot118021XGrpKey[key_index].skey, + keyparms->key, + (key_len > 16 ? 16 : key_len)); + + /* set mic key */ + memcpy(psecuritypriv-> + dot118021XGrptxmickey[key_index].skey, + &keyparms->key[16], 8); + memcpy(psecuritypriv-> + dot118021XGrprxmickey[key_index].skey, + &keyparms->key[24], 8); - set_group_key(padapter, param->u.crypt.key, - psecuritypriv-> - dot118021XGrpPrivacy, - param->u.crypt.idx); + psecuritypriv->busetkipkey = 1; + } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) { + psecuritypriv->dot118021XGrpPrivacy = + WLAN_CIPHER_SUITE_CCMP; - pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter); - if (pbcmc_sta) { - /* rx will use bmc_sta's - dot118021XPrivacy */ - pbcmc_sta->ieee8021x_blocked = false; - pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; - } + memcpy(psecuritypriv-> + dot118021XGrpKey[key_index].skey, + keyparms->key, + (key_len > 16 ? 16 : key_len)); + } else { + psecuritypriv->dot118021XGrpPrivacy = 0; + } + + psecuritypriv->dot118021XGrpKeyid = key_index; + + psecuritypriv->binstallGrpkey = 1; + + psecuritypriv->dot11PrivacyAlgrthm = + psecuritypriv->dot118021XGrpPrivacy; + + set_group_key(padapter, keyparms, + psecuritypriv->dot118021XGrpPrivacy, + key_index); + + pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter); + if (pbcmc_sta) { + /* rx will use bmc_sta's + dot118021XPrivacy */ + pbcmc_sta->ieee8021x_blocked = false; + pbcmc_sta->dot118021XPrivacy = + psecuritypriv->dot118021XGrpPrivacy; } } } @@ -873,80 +708,47 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, exit: return ret; - } #endif -static int rtw_cfg80211_set_encryption(struct net_device *dev, - struct ieee_param *param, u32 param_len) +static int rtw_cfg80211_set_encryption(struct net_device *dev, u8 key_index, + int set_tx, const u8 *sta_addr, + struct key_params *keyparms) { int ret = 0; - u32 wep_key_idx; - u16 wep_key_len; + int key_len; struct rtw_adapter *padapter = netdev_priv(dev); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct security_priv *psecuritypriv = &padapter->securitypriv; DBG_8723A("%s\n", __func__); - param->u.crypt.err = 0; - param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0'; - - if (param_len < - (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + - param->u.crypt.key_len) { - ret = -EINVAL; - goto exit; - } - - if (is_broadcast_ether_addr(param->sta_addr)) { - if (param->u.crypt.idx >= WEP_KEYS) { - ret = -EINVAL; - goto exit; - } - } else { - ret = -EINVAL; - goto exit; - } + key_len = keyparms->key_len; - if (strcmp(param->u.crypt.alg, "WEP") == 0) { + if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 || + keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) { RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("wpa_set_encryption, crypt.alg = WEP\n")); DBG_8723A("wpa_set_encryption, crypt.alg = WEP\n"); - wep_key_idx = param->u.crypt.idx; - wep_key_len = param->u.crypt.key_len; - - if ((wep_key_idx > WEP_KEYS) || (wep_key_len <= 0)) { - ret = -EINVAL; - goto exit; - } - if (psecuritypriv->bWepDefaultKeyIdxSet == 0) { /* wep default key has not been set, so use this key index as default key. */ - wep_key_len = wep_key_len <= 5 ? 5 : 13; - psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled; - psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40; - psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40; - - if (wep_key_len == 13) { - psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104; - psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP104; - } + psecuritypriv->dot11PrivacyAlgrthm = keyparms->cipher; + psecuritypriv->dot118021XGrpPrivacy = keyparms->cipher; - psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx; + psecuritypriv->dot11PrivacyKeyIndex = key_index; } - memcpy(&psecuritypriv->wep_key[wep_key_idx].key, - param->u.crypt.key, wep_key_len); + memcpy(&psecuritypriv->wep_key[key_index].key, + keyparms->key, key_len); - psecuritypriv->wep_key[wep_key_idx].keylen = wep_key_len; + psecuritypriv->wep_key[key_index].keylen = key_len; - rtw_set_key23a(padapter, psecuritypriv, wep_key_idx, 0); + rtw_set_key23a(padapter, psecuritypriv, key_index, 0); goto exit; } @@ -966,7 +768,8 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, } else { /* Jeff: don't disable ieee8021x_blocked while clearing key */ - if (strcmp(param->u.crypt.alg, "none") != 0) + if (keyparms->cipher != IW_AUTH_CIPHER_NONE && + keyparms->cipher != 0) psta->ieee8021x_blocked = false; if ((padapter->securitypriv.ndisencryptstatus == @@ -978,27 +781,23 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, dot11PrivacyAlgrthm; } - if (param->u.crypt.set_tx == 1) { + if (set_tx == 1) { /* pairwise key */ - DBG_8723A("%s, : param->u.crypt.set_tx" - " == 1\n", __func__); + DBG_8723A("%s, : set_tx == 1\n", + __func__); memcpy(psta->dot118021x_UncstKey.skey, - param->u.crypt.key, - (param->u.crypt.key_len > - 16 ? 16 : param->u.crypt. - key_len)); + keyparms->key, + (key_len > 16 ? 16 : key_len)); - if (strcmp(param->u.crypt.alg, - "TKIP") == 0) { + if (keyparms->cipher == + WLAN_CIPHER_SUITE_TKIP) { memcpy(psta->dot11tkiptxmickey. skey, - ¶m->u.crypt.key[16], - 8); + &keyparms->key[16], 8); memcpy(psta->dot11tkiprxmickey. skey, - ¶m->u.crypt.key[24], - 8); + &keyparms->key[24], 8); padapter->securitypriv. busetkipkey = 0; @@ -1010,36 +809,26 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, true); } else { /* group key */ memcpy(padapter->securitypriv. - dot118021XGrpKey[param->u.crypt. - idx].skey, - param->u.crypt.key, - (param->u.crypt.key_len > - 16 ? 16 : param->u.crypt. - key_len)); + dot118021XGrpKey[key_index].skey, + keyparms->key, + (key_len > 16 ? 16 : key_len)); memcpy(padapter->securitypriv. - dot118021XGrptxmickey[param->u. - crypt.idx]. - skey, ¶m->u.crypt.key[16], - 8); + dot118021XGrptxmickey[key_index]. + skey, &keyparms->key[16], 8); memcpy(padapter->securitypriv. - dot118021XGrprxmickey[param->u. - crypt.idx]. - skey, ¶m->u.crypt.key[24], - 8); + dot118021XGrprxmickey[key_index]. + skey, &keyparms->key[24], 8); padapter->securitypriv.binstallGrpkey = 1; - /* DEBUG_ERR((" param->u.crypt.key_len" - "=%d\n", param->u.crypt.key_len)); */ DBG_8723A (" ~~~~set sta key:groupkey\n"); padapter->securitypriv. - dot118021XGrpKeyid = - param->u.crypt.idx; + dot118021XGrpKeyid = key_index; rtw_set_key23a(padapter, &padapter->securitypriv, - param->u.crypt.idx, 1); + key_index, 1); } } @@ -1047,7 +836,8 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, if (pbcmc_sta) { /* Jeff: don't disable ieee8021x_blocked while clearing key */ - if (strcmp(param->u.crypt.alg, "none") != 0) + if (keyparms->cipher != IW_AUTH_CIPHER_NONE && + keyparms->cipher != 0) pbcmc_sta->ieee8021x_blocked = false; if ((padapter->securitypriv.ndisencryptstatus == @@ -1076,13 +866,11 @@ static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params) { - char *alg_name; - u32 param_len; - struct ieee_param *param; - int ret = 0; + int set_tx, ret = 0; struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy); struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + u8 sta_addr[ETH_ALEN]; DBG_8723A("%s(%s): adding key for %pM\n", __func__, ndev->name, mac_addr); @@ -1092,64 +880,48 @@ static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev, DBG_8723A("key_index =%d\n", key_index); DBG_8723A("pairwise =%d\n", pairwise); - param_len = sizeof(struct ieee_param) + params->key_len; - param = kzalloc(param_len, GFP_KERNEL); - if (!param) - return -ENOMEM; - - param->cmd = IEEE_CMD_SET_ENCRYPTION; - eth_broadcast_addr(param->sta_addr); - switch (params->cipher) { case IW_AUTH_CIPHER_NONE: - /* todo: remove key */ - /* remove = 1; */ - alg_name = "none"; - break; case WLAN_CIPHER_SUITE_WEP40: + if (params->key_len != WLAN_KEY_LEN_WEP40) { + ret = -EINVAL; + goto exit; + } case WLAN_CIPHER_SUITE_WEP104: - alg_name = "WEP"; - break; + if (params->key_len != WLAN_KEY_LEN_WEP104) { + ret = -EINVAL; + goto exit; + } case WLAN_CIPHER_SUITE_TKIP: - alg_name = "TKIP"; - break; case WLAN_CIPHER_SUITE_CCMP: - alg_name = "CCMP"; break; - default: ret = -ENOTSUPP; - goto addkey_end; + goto exit; } - strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN); - - if (!mac_addr || is_broadcast_ether_addr(mac_addr)) { - param->u.crypt.set_tx = 0; /* for wpa/wpa2 group key */ - } else { - param->u.crypt.set_tx = 1; /* for wpa/wpa2 pairwise key */ + if (key_index >= WEP_KEYS || params->key_len < 0) { + ret = -EINVAL; + goto exit; } - /* param->u.crypt.idx = key_index - 1; */ - param->u.crypt.idx = key_index; - - if (params->seq_len && params->seq) { - memcpy(param->u.crypt.seq, params->seq, params->seq_len); - } + eth_broadcast_addr(sta_addr); - if (params->key_len && params->key) { - param->u.crypt.key_len = params->key_len; - memcpy(param->u.crypt.key, params->key, params->key_len); - } + if (!mac_addr || is_broadcast_ether_addr(mac_addr)) + set_tx = 0; /* for wpa/wpa2 group key */ + else + set_tx = 1; /* for wpa/wpa2 pairwise key */ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - ret = rtw_cfg80211_set_encryption(ndev, param, param_len); + ret = rtw_cfg80211_set_encryption(ndev, key_index, set_tx, + sta_addr, params); } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { #ifdef CONFIG_8723AU_AP_MODE if (mac_addr) - ether_addr_copy(param->sta_addr, mac_addr); + ether_addr_copy(sta_addr, mac_addr); - ret = rtw_cfg80211_ap_set_encryption(ndev, param, param_len); + ret = rtw_cfg80211_ap_set_encryption(ndev, key_index, set_tx, + sta_addr, params); #endif } else { DBG_8723A("error! fw_state = 0x%x, iftype =%d\n", @@ -1157,9 +929,7 @@ static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev, } -addkey_end: - kfree(param); - +exit: return ret; } @@ -1225,6 +995,63 @@ static int cfg80211_rtw_set_default_key(struct wiphy *wiphy, return 0; } +static u16 rtw_get_cur_max_rate(struct rtw_adapter *adapter) +{ + int i = 0; + const u8 *p; + u16 rate = 0, max_rate = 0; + struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; + struct registry_priv *pregistrypriv = &adapter->registrypriv; + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; + struct ieee80211_ht_cap *pht_capie; + u8 rf_type = 0; + u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0; + u16 mcs_rate = 0; + + p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, + pcur_bss->IEs, pcur_bss->IELength); + if (p && p[1] > 0) { + pht_capie = (struct ieee80211_ht_cap *)(p + 2); + + memcpy(&mcs_rate, &pht_capie->mcs, 2); + + /* bw_40MHz = (pht_capie->cap_info& + IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1:0; */ + /* cur_bwmod is updated by beacon, pmlmeinfo is + updated by association response */ + bw_40MHz = (pmlmeext->cur_bwmode && + (pmlmeinfo->HT_info.ht_param & + IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) ? 1:0; + + /* short_GI = (pht_capie->cap_info & (IEEE80211_HT_CAP + _SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; */ + short_GI_20 = (pmlmeinfo->ht_cap.cap_info & + cpu_to_le16(IEEE80211_HT_CAP_SGI_20)) ? 1:0; + short_GI_40 = (pmlmeinfo->ht_cap.cap_info & + cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) ? 1:0; + + rf_type = rtl8723a_get_rf_type(adapter); + max_rate = rtw_mcs_rate23a(rf_type, bw_40MHz & + pregistrypriv->cbw40_enable, + short_GI_20, short_GI_40, + &pmlmeinfo->ht_cap.mcs); + } else { + while (pcur_bss->SupportedRates[i] != 0 && + pcur_bss->SupportedRates[i] != 0xFF) { + rate = pcur_bss->SupportedRates[i] & 0x7F; + if (rate>max_rate) + max_rate = rate; + i++; + } + + max_rate = max_rate * 10 / 2; + } + + return max_rate; +} + static int cfg80211_rtw_get_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac, struct station_info *sinfo) @@ -1269,7 +1096,7 @@ static int cfg80211_rtw_get_station(struct wiphy *wiphy, signal_strength); sinfo->filled |= STATION_INFO_TX_BITRATE; - sinfo->txrate.legacy = rtw_get_cur_max_rate23a(padapter); + sinfo->txrate.legacy = rtw_get_cur_max_rate(padapter); sinfo->filled |= STATION_INFO_RX_PACKETS; sinfo->rx_packets = sta_rx_data_pkts(psta); @@ -1479,16 +1306,17 @@ static int rtw_cfg80211_set_probe_req_wpsp2pie(struct rtw_adapter *padapter, char *buf, int len) { int ret = 0; - uint wps_ielen = 0; - u8 *wps_ie; + const u8 *wps_ie; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; DBG_8723A("%s, ielen =%d\n", __func__, len); if (len > 0) { - wps_ie = rtw_get_wps_ie23a(buf, len, NULL, &wps_ielen); + wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPS, + buf, len); if (wps_ie) { - DBG_8723A("probe_req_wps_ielen =%d\n", wps_ielen); + DBG_8723A("probe_req_wps_ielen =%d\n", wps_ie[1]); if (pmlmepriv->wps_probe_req_ie) { pmlmepriv->wps_probe_req_ie_len = 0; @@ -1496,15 +1324,14 @@ static int rtw_cfg80211_set_probe_req_wpsp2pie(struct rtw_adapter *padapter, pmlmepriv->wps_probe_req_ie = NULL; } - pmlmepriv->wps_probe_req_ie = kmemdup(wps_ie, - wps_ielen, + pmlmepriv->wps_probe_req_ie = kmemdup(wps_ie, wps_ie[1], GFP_KERNEL); if (pmlmepriv->wps_probe_req_ie == NULL) { DBG_8723A("%s()-%d: kmalloc() ERROR!\n", __func__, __LINE__); return -EINVAL; } - pmlmepriv->wps_probe_req_ie_len = wps_ielen; + pmlmepriv->wps_probe_req_ie_len = wps_ie[1]; } } @@ -1751,7 +1578,7 @@ static int rtw_cfg80211_set_key_mgt(struct security_priv *psecuritypriv, static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie, size_t ielen) { - u8 *buf = NULL; + const u8 *wps_ie; int group_cipher = 0, pairwise_cipher = 0; int ret = 0; const u8 *pwpa, *pwpa2; @@ -1767,19 +1594,14 @@ static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie, ret = -EINVAL; goto exit; } - buf = kmemdup(pie, ielen, GFP_KERNEL); - if (buf == NULL) { - ret = -ENOMEM; - goto exit; - } /* dump */ DBG_8723A("set wpa_ie(length:%zu):\n", ielen); for (i = 0; i < ielen; i = i + 8) - DBG_8723A("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", - buf[i], buf[i + 1], - buf[i + 2], buf[i + 3], buf[i + 4], - buf[i + 5], buf[i + 6], buf[i + 7]); + DBG_8723A("0x%.2x 0x%.2x 0x%.2x 0x%.2x " + "0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", + pie[i], pie[i + 1], pie[i + 2], pie[i + 3], + pie[i + 4], pie[i + 5], pie[i + 6], pie[i + 7]); if (ielen < RSN_HEADER_LEN) { RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("Ie len too short %d\n", (int)ielen)); @@ -1789,7 +1611,7 @@ static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie, pwpa = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPA, - buf, ielen); + pie, ielen); if (pwpa && pwpa[1] > 0) { if (rtw_parse_wpa_ie23a(pwpa, pwpa[1] + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { @@ -1804,7 +1626,7 @@ static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie, } } - pwpa2 = cfg80211_find_ie(WLAN_EID_RSN, buf, ielen); + pwpa2 = cfg80211_find_ie(WLAN_EID_RSN, pie, ielen); if (pwpa2 && pwpa2[1] > 0) { if (rtw_parse_wpa2_ie23a (pwpa2, pwpa2[1] + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { @@ -1882,22 +1704,17 @@ static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie, break; } - { /* handle wps_ie */ - uint wps_ielen; - u8 *wps_ie; - - wps_ie = rtw_get_wps_ie23a(buf, ielen, NULL, &wps_ielen); - if (wps_ie && wps_ielen > 0) { - DBG_8723A("got wps_ie, wps_ielen:%u\n", wps_ielen); - padapter->securitypriv.wps_ie_len = - wps_ielen < - MAX_WPS_IE_LEN ? wps_ielen : MAX_WPS_IE_LEN; - memcpy(padapter->securitypriv.wps_ie, wps_ie, - padapter->securitypriv.wps_ie_len); - set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS); - } else { - _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); - } + wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPS, + pie, ielen); + if (wps_ie && wps_ie[1] > 0) { + DBG_8723A("got wps_ie, wps_ielen:%u\n", wps_ie[1]); + padapter->securitypriv.wps_ie_len = wps_ie[1]; + memcpy(padapter->securitypriv.wps_ie, wps_ie, + padapter->securitypriv.wps_ie_len); + set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS); + } else { + _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); } /* TKIP and AES disallow multicast packets until installing group key */ @@ -1917,7 +1734,6 @@ static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie, padapter->securitypriv.ndisauthtype)); exit: - kfree(buf); if (ret) _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); return ret; @@ -1937,12 +1753,12 @@ static int rtw_cfg80211_add_wep(struct rtw_adapter *padapter, } switch (wep->keylen) { - case 5: + case WLAN_KEY_LEN_WEP40: psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40; RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("%s:wep->KeyLength = 5\n", __func__)); break; - case 13: + case WLAN_KEY_LEN_WEP104: psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104; RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("%s:wep->KeyLength = 13\n", __func__)); @@ -1987,18 +1803,162 @@ exit: return res; } +static int rtw_set_ssid(struct rtw_adapter *padapter, + struct wlan_network *newnetwork) +{ + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct wlan_network *pnetwork = &pmlmepriv->cur_network; + int status = _SUCCESS; + u32 cur_time = 0; + + DBG_8723A_LEVEL(_drv_always_, "set ssid [%s] fw_state = 0x%08x\n", + newnetwork->network.Ssid.ssid, get_fwstate(pmlmepriv)); + + if (padapter->hw_init_completed == false) { + RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, + ("set_ssid: hw_init_completed == false =>exit!!!\n")); + status = _FAIL; + goto exit; + } + + spin_lock_bh(&pmlmepriv->lock); + + DBG_8723A("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv)); + if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) + goto handle_tkip_countermeasure; + + if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) { + RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, + ("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n")); + + if (pmlmepriv->assoc_ssid.ssid_len == + newnetwork->network.Ssid.ssid_len && + !memcmp(&pmlmepriv->assoc_ssid.ssid, + newnetwork->network.Ssid.ssid, + newnetwork->network.Ssid.ssid_len)) { + if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { + RT_TRACE(_module_rtl871x_ioctl_set_c_, + _drv_err_, ("New SSID is same SSID, " + "fw_state = 0x%08x\n", + get_fwstate(pmlmepriv))); + + if (rtw_is_same_ibss23a(padapter, pnetwork)) { + /* + * it means driver is in + * WIFI_ADHOC_MASTER_STATE, we needn't + * create bss again. + */ + goto release_mlme_lock; + } + + /* + * if in WIFI_ADHOC_MASTER_STATE | + * WIFI_ADHOC_STATE, create bss or + * rejoin again + */ + rtw_disassoc_cmd23a(padapter, 0, true); + + if (check_fwstate(pmlmepriv, _FW_LINKED)) + rtw_indicate_disconnect23a(padapter); + + rtw_free_assoc_resources23a(padapter, 1); + + if (check_fwstate(pmlmepriv, + WIFI_ADHOC_MASTER_STATE)) { + _clr_fwstate_(pmlmepriv, + WIFI_ADHOC_MASTER_STATE); + set_fwstate(pmlmepriv, + WIFI_ADHOC_STATE); + } + } else { + rtw_lps_ctrl_wk_cmd23a(padapter, + LPS_CTRL_JOINBSS, 1); + } + } else { + RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, + ("Set SSID not the same ssid\n")); + RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, + ("set_ssid =[%s] len = 0x%x\n", + newnetwork->network.Ssid.ssid, + newnetwork->network.Ssid.ssid_len)); + RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, + ("assoc_ssid =[%s] len = 0x%x\n", + pmlmepriv->assoc_ssid.ssid, + pmlmepriv->assoc_ssid.ssid_len)); + + rtw_disassoc_cmd23a(padapter, 0, true); + + if (check_fwstate(pmlmepriv, _FW_LINKED)) + rtw_indicate_disconnect23a(padapter); + + rtw_free_assoc_resources23a(padapter, 1); + + if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { + _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE); + set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); + } + } + } + +handle_tkip_countermeasure: + + if (padapter->securitypriv.btkip_countermeasure == true) { + cur_time = jiffies; + + if ((cur_time - + padapter->securitypriv.btkip_countermeasure_time) > + 60 * HZ) { + padapter->securitypriv.btkip_countermeasure = false; + padapter->securitypriv.btkip_countermeasure_time = 0; + } else { + status = _FAIL; + goto release_mlme_lock; + } + } + + memcpy(&pmlmepriv->assoc_ssid, &newnetwork->network.Ssid, + sizeof(struct cfg80211_ssid)); + + pmlmepriv->assoc_by_bssid = false; + + pmlmepriv->to_join = true; + + if (!check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) { + pmlmepriv->cur_network.join_res = -2; + + status = rtw_do_join_network(padapter, newnetwork); + if (status == _SUCCESS) { + pmlmepriv->to_join = false; + } else { + if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { + /* switch to ADHOC_MASTER */ + status = rtw_do_join_adhoc(padapter); + if (status != _SUCCESS) + goto release_mlme_lock; + } else { + /* can't associate ; reset under-linking */ + _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); + status = _FAIL; + pmlmepriv->to_join = false; + } + } + } +release_mlme_lock: + spin_unlock_bh(&pmlmepriv->lock); + +exit: + RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, + ("-%s: status =%d\n", __func__, status)); + + return status; +} + static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *sme) { int ret = 0; struct list_head *phead, *plist, *ptmp; struct wlan_network *pnetwork = NULL; - enum ndis_802_11_auth_mode authmode; - struct cfg80211_ssid ndis_ssid; - u8 *dst_ssid; - u8 *src_ssid; - u8 *dst_bssid; - const u8 *src_bssid; /* u8 matched_by_bssid = false; */ /* u8 matched_by_ssid = false; */ u8 matched = false; @@ -2021,21 +1981,13 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev, goto exit; } - if (!sme->ssid || !sme->ssid_len) { + if (!sme->ssid || !sme->ssid_len || + sme->ssid_len > IEEE80211_MAX_SSID_LEN) { ret = -EINVAL; goto exit; } - if (sme->ssid_len > IW_ESSID_MAX_SIZE) { - ret = -E2BIG; - goto exit; - } - - memset(&ndis_ssid, 0, sizeof(struct cfg80211_ssid)); - ndis_ssid.ssid_len = sme->ssid_len; - memcpy(ndis_ssid.ssid, sme->ssid, sme->ssid_len); - - DBG_8723A("ssid =%s, len =%zu\n", ndis_ssid.ssid, sme->ssid_len); + DBG_8723A("ssid =%s, len =%zu\n", sme->ssid, sme->ssid_len); if (sme->bssid) DBG_8723A("bssid =" MAC_FMT "\n", MAC_ARG(sme->bssid)); @@ -2057,9 +2009,6 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev, list_for_each_safe(plist, ptmp, phead) { pnetwork = container_of(plist, struct wlan_network, list); - dst_ssid = pnetwork->network.Ssid.ssid; - dst_bssid = pnetwork->network.MacAddress; - if (sme->bssid) { if (!ether_addr_equal(pnetwork->network.MacAddress, sme->bssid)) @@ -2074,28 +2023,19 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev, } if (sme->bssid) { - src_bssid = sme->bssid; - - if (ether_addr_equal(dst_bssid, src_bssid)) { + if (ether_addr_equal(pnetwork->network.MacAddress, + sme->bssid)) { DBG_8723A("matched by bssid\n"); - ndis_ssid.ssid_len = - pnetwork->network.Ssid.ssid_len; - memcpy(ndis_ssid.ssid, - pnetwork->network.Ssid.ssid, - pnetwork->network.Ssid.ssid_len); - matched = true; break; } - } else if (sme->ssid && sme->ssid_len) { - src_ssid = ndis_ssid.ssid; - - if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.ssid_len)) && - (pnetwork->network.Ssid.ssid_len == - ndis_ssid.ssid_len)) { + if (!memcmp(pnetwork->network.Ssid.ssid, + sme->ssid, sme->ssid_len) && + pnetwork->network.Ssid.ssid_len == sme->ssid_len) { DBG_8723A("matched by ssid\n"); + matched = true; break; } @@ -2104,7 +2044,7 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev, spin_unlock_bh(&queue->lock); - if (!matched || (pnetwork == NULL)) { + if (!matched || !pnetwork) { ret = -ENOENT; DBG_8723A("connect, matched == false, goto exit\n"); goto exit; @@ -2122,9 +2062,8 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev, psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen; - ret = - rtw_cfg80211_set_wpa_version(psecuritypriv, - sme->crypto.wpa_versions); + ret = rtw_cfg80211_set_wpa_version(psecuritypriv, + sme->crypto.wpa_versions); if (ret < 0) goto exit; @@ -2195,7 +2134,7 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev, ret = rtw_cfg80211_set_cipher(psecuritypriv, sme->crypto.cipher_group, false); if (ret < 0) - return ret; + goto exit; if (sme->crypto.n_akm_suites) { ret = rtw_cfg80211_set_key_mgt(psecuritypriv, @@ -2204,14 +2143,19 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev, goto exit; } - authmode = psecuritypriv->ndisauthtype; - rtw_set_802_11_authentication_mode23a(padapter, authmode); + if (psecuritypriv->ndisauthtype > 3) + psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; + + if (rtw_set_auth23a(padapter, psecuritypriv) != _SUCCESS) { + ret = -EBUSY; + goto exit; + } /* rtw_set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */ - if (rtw_set_802_11_ssid23a(padapter, &ndis_ssid) == false) { - ret = -1; + if (rtw_set_ssid(padapter, pnetwork) != _SUCCESS) { + ret = -EBUSY; goto exit; } @@ -2411,16 +2355,18 @@ void rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter, { struct station_info sinfo; u8 ie_offset; + if (ieee80211_is_assoc_req(hdr->frame_control)) - ie_offset = _ASOCREQ_IE_OFFSET_; + ie_offset = offsetof(struct ieee80211_mgmt, + u.assoc_req.variable); else /* WIFI_REASSOCREQ */ - ie_offset = _REASOCREQ_IE_OFFSET_; + ie_offset = offsetof(struct ieee80211_mgmt, + u.reassoc_req.variable); sinfo.filled = 0; sinfo.filled = STATION_INFO_ASSOC_REQ_IES; - sinfo.assoc_req_ies = pmgmt_frame + WLAN_HDR_A3_LEN + ie_offset; - sinfo.assoc_req_ies_len = - frame_len - WLAN_HDR_A3_LEN - ie_offset; + sinfo.assoc_req_ies = pmgmt_frame + ie_offset; + sinfo.assoc_req_ies_len = frame_len - ie_offset; cfg80211_new_sta(ndev, hdr->addr2, &sinfo, GFP_ATOMIC); } #else /* defined(RTW_USE_CFG80211_STA_EVENT) */ @@ -2443,17 +2389,15 @@ void rtw_cfg80211_indicate_sta_disassoc(struct rtw_adapter *padapter, { s32 freq; int channel; - u8 *pmgmt_frame; uint frame_len; - struct ieee80211_hdr *pwlanhdr; - u8 mgmt_buf[128]; + struct ieee80211_mgmt mgmt; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; struct net_device *ndev = padapter->pnetdev; DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name); - memset(mgmt_buf, 0, 128); + memset(&mgmt, 0, sizeof(struct ieee80211_mgmt)); #if defined(RTW_USE_CFG80211_STA_EVENT) cfg80211_del_sta(ndev, da, GFP_ATOMIC); @@ -2466,29 +2410,21 @@ void rtw_cfg80211_indicate_sta_disassoc(struct rtw_adapter *padapter, freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ); - pmgmt_frame = mgmt_buf; - pwlanhdr = (struct ieee80211_hdr *)pmgmt_frame; - - pwlanhdr->frame_control = + mgmt.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); - ether_addr_copy(pwlanhdr->addr1, myid(&padapter->eeprompriv)); - ether_addr_copy(pwlanhdr->addr2, da); - ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network)); + ether_addr_copy(mgmt.da, myid(&padapter->eeprompriv)); + ether_addr_copy(mgmt.sa, da); + ether_addr_copy(mgmt.bssid, get_my_bssid23a(&pmlmeinfo->network)); - pwlanhdr->seq_ctrl = - cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); + mgmt.seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); pmlmeext->mgnt_seq++; - pmgmt_frame += sizeof(struct ieee80211_hdr_3addr); - frame_len = sizeof(struct ieee80211_hdr_3addr); + mgmt.u.disassoc.reason_code = cpu_to_le16(reason); - reason = cpu_to_le16(reason); - pmgmt_frame = rtw_set_fixed_ie23a(pmgmt_frame, - WLAN_REASON_PREV_AUTH_NOT_VALID, - (unsigned char *)&reason, &frame_len); + frame_len = sizeof(struct ieee80211_hdr_3addr) + 2; - cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, mgmt_buf, frame_len, + cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, (u8 *)&mgmt, frame_len, 0, GFP_ATOMIC); #endif /* defined(RTW_USE_CFG80211_STA_EVENT) */ } @@ -2597,11 +2533,8 @@ static int rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, MAC_ARG(mgmt->da), __func__, ndev->name); category = mgmt->u.action.category; action = mgmt->u.action.u.wme_action.action_code; - if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) - DBG_8723A("RTW_Tx:%s\n", action_public_str23a(action)); - else - DBG_8723A("RTW_Tx:category(%u), action(%u)\n", category, - action); + DBG_8723A("RTW_Tx:category(%u), action(%u)\n", + category, action); /* starting alloc mgmt frame to dump it */ pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); @@ -2801,9 +2734,12 @@ static int rtw_add_beacon(struct rtw_adapter *adapter, const u8 *head, size_t head_len, const u8 *tail, size_t tail_len) { int ret = 0; - u8 *pbuf = NULL; - uint len, wps_ielen = 0; + u8 *pbuf; + uint len, ielen, wps_ielen = 0; struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + struct wlan_bssid_ex *bss = &pmlmepriv->cur_network.network; + const struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)head; + struct ieee80211_mgmt *tmpmgmt; /* struct sta_priv *pstapriv = &padapter->stapriv; */ DBG_8723A("%s beacon_head_len =%zu, beacon_tail_len =%zu\n", @@ -2812,31 +2748,38 @@ static int rtw_add_beacon(struct rtw_adapter *adapter, const u8 *head, if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) return -EINVAL; - if (head_len < 24) + if (head_len < offsetof(struct ieee80211_mgmt, u.beacon.variable)) return -EINVAL; pbuf = kzalloc(head_len + tail_len, GFP_KERNEL); if (!pbuf) return -ENOMEM; - /* 24 = beacon header len. */ - memcpy(pbuf, (void *)head + 24, head_len - 24); - memcpy(pbuf + head_len - 24, (void *)tail, tail_len); + tmpmgmt = (struct ieee80211_mgmt *)pbuf; + + bss->beacon_interval = get_unaligned_le16(&mgmt->u.beacon.beacon_int); + bss->capability = get_unaligned_le16(&mgmt->u.beacon.capab_info); + bss->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp); - len = head_len + tail_len - 24; + /* 24 = beacon header len. */ + memcpy(pbuf, (void *)head, head_len); + memcpy(pbuf + head_len, (void *)tail, tail_len); + len = head_len + tail_len; + ielen = len - offsetof(struct ieee80211_mgmt, u.beacon.variable); /* check wps ie if inclued */ - if (rtw_get_wps_ie23a - (pbuf + _FIXED_IE_LENGTH_, len - _FIXED_IE_LENGTH_, NULL, - &wps_ielen)) + if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPS, + tmpmgmt->u.beacon.variable, ielen)) DBG_8723A("add bcn, wps_ielen =%d\n", wps_ielen); /* pbss_network->IEs will not include p2p_ie, wfd ie */ - rtw_ies_remove_ie23a(pbuf, &len, _BEACON_IE_OFFSET_, + rtw_ies_remove_ie23a(tmpmgmt->u.beacon.variable, &ielen, 0, WLAN_EID_VENDOR_SPECIFIC, P2P_OUI23A, 4); - rtw_ies_remove_ie23a(pbuf, &len, _BEACON_IE_OFFSET_, + rtw_ies_remove_ie23a(tmpmgmt->u.beacon.variable, &ielen, 0, WLAN_EID_VENDOR_SPECIFIC, WFD_OUI23A, 4); - if (rtw_check_beacon_data23a(adapter, pbuf, len) == _SUCCESS) { + len = ielen + offsetof(struct ieee80211_mgmt, u.beacon.variable); + if (rtw_check_beacon_data23a(adapter, tmpmgmt, len) == _SUCCESS) { ret = 0; } else { ret = -EINVAL; @@ -3014,34 +2957,6 @@ static int cfg80211_rtw_change_bss(struct wiphy *wiphy, struct net_device *ndev, } #endif /* CONFIG_8723AU_AP_MODE */ -void rtw_cfg80211_rx_action(struct rtw_adapter *adapter, u8 *frame, - uint frame_len, const char *msg) -{ - struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *)frame; - s32 freq; - int channel; - - channel = rtw_get_oper_ch23a(adapter); - - DBG_8723A("RTW_Rx:cur_ch =%d\n", channel); - if (msg) - DBG_8723A("RTW_Rx:%s\n", msg); - else - DBG_8723A("RTW_Rx:category(%u), action(%u)\n", - hdr->u.action.category, - hdr->u.action.u.wme_action.action_code); - - if (channel <= RTW_CH_MAX_2G_CHANNEL) - freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_2GHZ); - else - freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_5GHZ); - - cfg80211_rx_mgmt(adapter->rtw_wdev, freq, 0, frame, frame_len, - 0, GFP_ATOMIC); -} - static int _cfg80211_rtw_mgmt_tx(struct rtw_adapter *padapter, u8 tx_ch, const u8 *buf, size_t len) { @@ -3148,11 +3063,7 @@ static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, MAC_ARG(hdr->da)); category = hdr->u.action.category; action = hdr->u.action.u.wme_action.action_code; - if (category == WLAN_CATEGORY_PUBLIC) - DBG_8723A("RTW_Tx:%s\n", action_public_str23a(action)); - else - DBG_8723A("RTW_Tx:category(%u), action(%u)\n", - category, action); + DBG_8723A("RTW_Tx:category(%u), action(%u)\n", category, action); do { dump_cnt++; |