|
@@ -21,31 +21,11 @@
|
|
|
*
|
|
|
*/
|
|
|
|
|
|
-#include <linux/kernel.h>
|
|
|
-#include <linux/netdevice.h>
|
|
|
#include <linux/wireless.h>
|
|
|
-#include <linux/if_arp.h>
|
|
|
-#include <linux/etherdevice.h>
|
|
|
#include <net/cfg80211.h>
|
|
|
-#include <net/iw_handler.h>
|
|
|
|
|
|
#include "iwm.h"
|
|
|
-#include "umac.h"
|
|
|
#include "commands.h"
|
|
|
-#include "debug.h"
|
|
|
-
|
|
|
-static struct iw_statistics *iwm_get_wireless_stats(struct net_device *dev)
|
|
|
-{
|
|
|
- struct iwm_priv *iwm = ndev_to_iwm(dev);
|
|
|
- struct iw_statistics *wstats = &iwm->wstats;
|
|
|
-
|
|
|
- if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
|
|
|
- memset(wstats, 0, sizeof(struct iw_statistics));
|
|
|
- wstats->qual.updated = IW_QUAL_ALL_INVALID;
|
|
|
- }
|
|
|
-
|
|
|
- return wstats;
|
|
|
-}
|
|
|
|
|
|
static int iwm_wext_siwfreq(struct net_device *dev,
|
|
|
struct iw_request_info *info,
|
|
@@ -53,14 +33,12 @@ static int iwm_wext_siwfreq(struct net_device *dev,
|
|
|
{
|
|
|
struct iwm_priv *iwm = ndev_to_iwm(dev);
|
|
|
|
|
|
- if (freq->flags == IW_FREQ_AUTO)
|
|
|
- return 0;
|
|
|
-
|
|
|
- /* frequency/channel can only be set in IBSS mode */
|
|
|
- if (iwm->conf.mode != UMAC_MODE_IBSS)
|
|
|
+ switch (iwm->conf.mode) {
|
|
|
+ case UMAC_MODE_IBSS:
|
|
|
+ return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra);
|
|
|
+ default:
|
|
|
return -EOPNOTSUPP;
|
|
|
-
|
|
|
- return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static int iwm_wext_giwfreq(struct net_device *dev,
|
|
@@ -69,69 +47,29 @@ static int iwm_wext_giwfreq(struct net_device *dev,
|
|
|
{
|
|
|
struct iwm_priv *iwm = ndev_to_iwm(dev);
|
|
|
|
|
|
- if (iwm->conf.mode == UMAC_MODE_IBSS)
|
|
|
+ switch (iwm->conf.mode) {
|
|
|
+ case UMAC_MODE_IBSS:
|
|
|
return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
|
|
|
-
|
|
|
- freq->e = 0;
|
|
|
- freq->m = iwm->channel;
|
|
|
-
|
|
|
- return 0;
|
|
|
+ case UMAC_MODE_BSS:
|
|
|
+ return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra);
|
|
|
+ default:
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info,
|
|
|
struct sockaddr *ap_addr, char *extra)
|
|
|
{
|
|
|
struct iwm_priv *iwm = ndev_to_iwm(dev);
|
|
|
- int ret;
|
|
|
-
|
|
|
- IWM_DBG_WEXT(iwm, DBG, "Set BSSID: %pM\n", ap_addr->sa_data);
|
|
|
|
|
|
- if (iwm->conf.mode == UMAC_MODE_IBSS)
|
|
|
+ switch (iwm->conf.mode) {
|
|
|
+ case UMAC_MODE_IBSS:
|
|
|
return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
|
|
|
-
|
|
|
- if (!test_bit(IWM_STATUS_READY, &iwm->status))
|
|
|
- return -EIO;
|
|
|
-
|
|
|
- if (is_zero_ether_addr(ap_addr->sa_data) ||
|
|
|
- is_broadcast_ether_addr(ap_addr->sa_data)) {
|
|
|
- IWM_DBG_WEXT(iwm, DBG, "clear mandatory bssid %pM\n",
|
|
|
- iwm->umac_profile->bssid[0]);
|
|
|
- memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
|
|
|
- iwm->umac_profile->bss_num = 0;
|
|
|
- } else {
|
|
|
- IWM_DBG_WEXT(iwm, DBG, "add mandatory bssid %pM\n",
|
|
|
- ap_addr->sa_data);
|
|
|
- memcpy(&iwm->umac_profile->bssid[0], ap_addr->sa_data,
|
|
|
- ETH_ALEN);
|
|
|
- iwm->umac_profile->bss_num = 1;
|
|
|
- }
|
|
|
-
|
|
|
- if (iwm->umac_profile_active) {
|
|
|
- int i;
|
|
|
-
|
|
|
- if (!memcmp(&iwm->umac_profile->bssid[0], iwm->bssid, ETH_ALEN))
|
|
|
- return 0;
|
|
|
-
|
|
|
- /*
|
|
|
- * If we're clearing the BSSID, and we're associated,
|
|
|
- * we have to clear the keys as they're no longer valid.
|
|
|
- */
|
|
|
- if (is_zero_ether_addr(ap_addr->sa_data)) {
|
|
|
- for (i = 0; i < IWM_NUM_KEYS; i++)
|
|
|
- iwm->keys[i].key_len = 0;
|
|
|
- }
|
|
|
-
|
|
|
- ret = iwm_invalidate_mlme_profile(iwm);
|
|
|
- if (ret < 0) {
|
|
|
- IWM_ERR(iwm, "Couldn't invalidate profile\n");
|
|
|
- return ret;
|
|
|
- }
|
|
|
+ case UMAC_MODE_BSS:
|
|
|
+ return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra);
|
|
|
+ default:
|
|
|
+ return -EOPNOTSUPP;
|
|
|
}
|
|
|
-
|
|
|
- if (iwm->umac_profile->ssid.ssid_len)
|
|
|
- return iwm_send_mlme_profile(iwm);
|
|
|
-
|
|
|
- return 0;
|
|
|
}
|
|
|
|
|
|
static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info,
|
|
@@ -143,17 +81,10 @@ static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info,
|
|
|
case UMAC_MODE_IBSS:
|
|
|
return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
|
|
|
case UMAC_MODE_BSS:
|
|
|
- if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
|
|
|
- ap_addr->sa_family = ARPHRD_ETHER;
|
|
|
- memcpy(&ap_addr->sa_data, iwm->bssid, ETH_ALEN);
|
|
|
- } else
|
|
|
- memset(&ap_addr->sa_data, 0, ETH_ALEN);
|
|
|
- break;
|
|
|
+ return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra);
|
|
|
default:
|
|
|
return -EOPNOTSUPP;
|
|
|
}
|
|
|
-
|
|
|
- return 0;
|
|
|
}
|
|
|
|
|
|
static int iwm_wext_siwessid(struct net_device *dev,
|
|
@@ -161,36 +92,15 @@ static int iwm_wext_siwessid(struct net_device *dev,
|
|
|
struct iw_point *data, char *ssid)
|
|
|
{
|
|
|
struct iwm_priv *iwm = ndev_to_iwm(dev);
|
|
|
- size_t len = data->length;
|
|
|
- int ret;
|
|
|
-
|
|
|
- IWM_DBG_WEXT(iwm, DBG, "Set ESSID: >%s<\n", ssid);
|
|
|
|
|
|
- if (iwm->conf.mode == UMAC_MODE_IBSS)
|
|
|
+ switch (iwm->conf.mode) {
|
|
|
+ case UMAC_MODE_IBSS:
|
|
|
return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
|
|
|
-
|
|
|
- if (!test_bit(IWM_STATUS_READY, &iwm->status))
|
|
|
- return -EIO;
|
|
|
-
|
|
|
- if (len > 0 && ssid[len - 1] == '\0')
|
|
|
- len--;
|
|
|
-
|
|
|
- if (iwm->umac_profile_active) {
|
|
|
- if (iwm->umac_profile->ssid.ssid_len == len &&
|
|
|
- !memcmp(iwm->umac_profile->ssid.ssid, ssid, len))
|
|
|
- return 0;
|
|
|
-
|
|
|
- ret = iwm_invalidate_mlme_profile(iwm);
|
|
|
- if (ret < 0) {
|
|
|
- IWM_ERR(iwm, "Couldn't invalidate profile\n");
|
|
|
- return ret;
|
|
|
- }
|
|
|
+ case UMAC_MODE_BSS:
|
|
|
+ return cfg80211_mgd_wext_siwessid(dev, info, data, ssid);
|
|
|
+ default:
|
|
|
+ return -EOPNOTSUPP;
|
|
|
}
|
|
|
-
|
|
|
- iwm->umac_profile->ssid.ssid_len = len;
|
|
|
- memcpy(iwm->umac_profile->ssid.ssid, ssid, len);
|
|
|
-
|
|
|
- return iwm_send_mlme_profile(iwm);
|
|
|
}
|
|
|
|
|
|
static int iwm_wext_giwessid(struct net_device *dev,
|
|
@@ -199,174 +109,14 @@ static int iwm_wext_giwessid(struct net_device *dev,
|
|
|
{
|
|
|
struct iwm_priv *iwm = ndev_to_iwm(dev);
|
|
|
|
|
|
- if (iwm->conf.mode == UMAC_MODE_IBSS)
|
|
|
+ switch (iwm->conf.mode) {
|
|
|
+ case UMAC_MODE_IBSS:
|
|
|
return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
|
|
|
-
|
|
|
- if (!test_bit(IWM_STATUS_READY, &iwm->status))
|
|
|
- return -EIO;
|
|
|
-
|
|
|
- data->length = iwm->umac_profile->ssid.ssid_len;
|
|
|
- if (data->length) {
|
|
|
- memcpy(ssid, iwm->umac_profile->ssid.ssid, data->length);
|
|
|
- data->flags = 1;
|
|
|
- } else
|
|
|
- data->flags = 0;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int iwm_wext_giwrate(struct net_device *dev,
|
|
|
- struct iw_request_info *info,
|
|
|
- struct iw_param *rate, char *extra)
|
|
|
-{
|
|
|
- struct iwm_priv *iwm = ndev_to_iwm(dev);
|
|
|
-
|
|
|
- rate->value = iwm->rate * 1000000;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int iwm_set_wpa_version(struct iwm_priv *iwm, u8 wpa_version)
|
|
|
-{
|
|
|
- if (wpa_version & IW_AUTH_WPA_VERSION_WPA2)
|
|
|
- iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
|
|
|
- else if (wpa_version & IW_AUTH_WPA_VERSION_WPA)
|
|
|
- iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK;
|
|
|
- else
|
|
|
- iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int iwm_set_key_mgt(struct iwm_priv *iwm, u8 key_mgt)
|
|
|
-{
|
|
|
- u8 *auth_type = &iwm->umac_profile->sec.auth_type;
|
|
|
-
|
|
|
- IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
|
|
|
-
|
|
|
- if (key_mgt == IW_AUTH_KEY_MGMT_802_1X)
|
|
|
- *auth_type = UMAC_AUTH_TYPE_8021X;
|
|
|
- else if (key_mgt == IW_AUTH_KEY_MGMT_PSK) {
|
|
|
- if (iwm->umac_profile->sec.flags &
|
|
|
- (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
|
|
|
- *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
|
|
|
- else
|
|
|
- *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
|
|
|
- } else {
|
|
|
- IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int iwm_set_cipher(struct iwm_priv *iwm, u8 cipher, u8 ucast)
|
|
|
-{
|
|
|
- u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
|
|
|
- &iwm->umac_profile->sec.mcast_cipher;
|
|
|
-
|
|
|
- switch (cipher) {
|
|
|
- case IW_AUTH_CIPHER_NONE:
|
|
|
- *profile_cipher = UMAC_CIPHER_TYPE_NONE;
|
|
|
- break;
|
|
|
- case IW_AUTH_CIPHER_WEP40:
|
|
|
- *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
|
|
|
- break;
|
|
|
- case IW_AUTH_CIPHER_TKIP:
|
|
|
- *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
|
|
|
- break;
|
|
|
- case IW_AUTH_CIPHER_CCMP:
|
|
|
- *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
|
|
|
- break;
|
|
|
- case IW_AUTH_CIPHER_WEP104:
|
|
|
- *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
|
|
|
- break;
|
|
|
- default:
|
|
|
- IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
|
|
|
- return -ENOTSUPP;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int iwm_set_auth_alg(struct iwm_priv *iwm, u8 auth_alg)
|
|
|
-{
|
|
|
- u8 *auth_type = &iwm->umac_profile->sec.auth_type;
|
|
|
-
|
|
|
- IWM_DBG_WEXT(iwm, DBG, "auth_alg: 0x%x\n", auth_alg);
|
|
|
-
|
|
|
- switch (auth_alg) {
|
|
|
- case IW_AUTH_ALG_OPEN_SYSTEM:
|
|
|
- *auth_type = UMAC_AUTH_TYPE_OPEN;
|
|
|
- break;
|
|
|
- case IW_AUTH_ALG_SHARED_KEY:
|
|
|
- if (iwm->umac_profile->sec.flags &
|
|
|
- (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
|
|
|
- if (*auth_type == UMAC_AUTH_TYPE_8021X)
|
|
|
- return -EINVAL;
|
|
|
- *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
|
|
|
- } else {
|
|
|
- IWM_DBG_WEXT(iwm, DBG, "WEP shared key\n");
|
|
|
- *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
|
|
|
- }
|
|
|
- break;
|
|
|
- case IW_AUTH_ALG_LEAP:
|
|
|
- default:
|
|
|
- IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", auth_alg);
|
|
|
- return -ENOTSUPP;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int iwm_wext_siwauth(struct net_device *dev,
|
|
|
- struct iw_request_info *info,
|
|
|
- struct iw_param *data, char *extra)
|
|
|
-{
|
|
|
- struct iwm_priv *iwm = ndev_to_iwm(dev);
|
|
|
- int ret;
|
|
|
-
|
|
|
- if ((data->flags) &
|
|
|
- (IW_AUTH_WPA_VERSION | IW_AUTH_KEY_MGMT |
|
|
|
- IW_AUTH_WPA_ENABLED | IW_AUTH_80211_AUTH_ALG)) {
|
|
|
- /* We need to invalidate the current profile */
|
|
|
- if (iwm->umac_profile_active) {
|
|
|
- ret = iwm_invalidate_mlme_profile(iwm);
|
|
|
- if (ret < 0) {
|
|
|
- IWM_ERR(iwm, "Couldn't invalidate profile\n");
|
|
|
- return ret;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- switch (data->flags & IW_AUTH_INDEX) {
|
|
|
- case IW_AUTH_WPA_VERSION:
|
|
|
- return iwm_set_wpa_version(iwm, data->value);
|
|
|
- break;
|
|
|
- case IW_AUTH_CIPHER_PAIRWISE:
|
|
|
- return iwm_set_cipher(iwm, data->value, 1);
|
|
|
- break;
|
|
|
- case IW_AUTH_CIPHER_GROUP:
|
|
|
- return iwm_set_cipher(iwm, data->value, 0);
|
|
|
- break;
|
|
|
- case IW_AUTH_KEY_MGMT:
|
|
|
- return iwm_set_key_mgt(iwm, data->value);
|
|
|
- break;
|
|
|
- case IW_AUTH_80211_AUTH_ALG:
|
|
|
- return iwm_set_auth_alg(iwm, data->value);
|
|
|
- break;
|
|
|
+ case UMAC_MODE_BSS:
|
|
|
+ return cfg80211_mgd_wext_giwessid(dev, info, data, ssid);
|
|
|
default:
|
|
|
- return -ENOTSUPP;
|
|
|
+ return -EOPNOTSUPP;
|
|
|
}
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int iwm_wext_giwauth(struct net_device *dev,
|
|
|
- struct iw_request_info *info,
|
|
|
- struct iw_param *data, char *extra)
|
|
|
-{
|
|
|
- return 0;
|
|
|
}
|
|
|
|
|
|
static const iw_handler iwm_handlers[] =
|
|
@@ -404,7 +154,7 @@ static const iw_handler iwm_handlers[] =
|
|
|
(iw_handler) NULL, /* -- hole -- */
|
|
|
(iw_handler) NULL, /* -- hole -- */
|
|
|
(iw_handler) NULL, /* SIOCSIWRATE */
|
|
|
- (iw_handler) iwm_wext_giwrate, /* SIOCGIWRATE */
|
|
|
+ (iw_handler) cfg80211_wext_giwrate, /* SIOCGIWRATE */
|
|
|
(iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */
|
|
|
(iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */
|
|
|
(iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */
|
|
@@ -419,10 +169,10 @@ static const iw_handler iwm_handlers[] =
|
|
|
(iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */
|
|
|
(iw_handler) NULL, /* -- hole -- */
|
|
|
(iw_handler) NULL, /* -- hole -- */
|
|
|
- (iw_handler) NULL, /* SIOCSIWGENIE */
|
|
|
+ (iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */
|
|
|
(iw_handler) NULL, /* SIOCGIWGENIE */
|
|
|
- (iw_handler) iwm_wext_siwauth, /* SIOCSIWAUTH */
|
|
|
- (iw_handler) iwm_wext_giwauth, /* SIOCGIWAUTH */
|
|
|
+ (iw_handler) cfg80211_wext_siwauth, /* SIOCSIWAUTH */
|
|
|
+ (iw_handler) cfg80211_wext_giwauth, /* SIOCGIWAUTH */
|
|
|
(iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */
|
|
|
(iw_handler) NULL, /* SIOCGIWENCODEEXT */
|
|
|
(iw_handler) NULL, /* SIOCSIWPMKSA */
|
|
@@ -432,6 +182,6 @@ static const iw_handler iwm_handlers[] =
|
|
|
const struct iw_handler_def iwm_iw_handler_def = {
|
|
|
.num_standard = ARRAY_SIZE(iwm_handlers),
|
|
|
.standard = (iw_handler *) iwm_handlers,
|
|
|
- .get_wireless_stats = iwm_get_wireless_stats,
|
|
|
+ .get_wireless_stats = cfg80211_wireless_stats,
|
|
|
};
|
|
|
|