]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/mac80211/wext.c
mac80211: disable moving between PS modes during scan
[karo-tx-linux.git] / net / mac80211 / wext.c
index 1eb6d8642a77138510bc9eb6ecaf420c57369676..d2d81b103341472613d8dabe14c3fda20c21c01b 100644 (file)
 #include "aes_ccm.h"
 
 
-static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta_addr,
-                                   int idx, int alg, int remove,
-                                   int set_tx_key, const u8 *_key,
-                                   size_t key_len)
-{
-       struct ieee80211_local *local = sdata->local;
-       struct sta_info *sta;
-       struct ieee80211_key *key;
-       int err;
-
-       if (alg == ALG_AES_CMAC) {
-               if (idx < NUM_DEFAULT_KEYS ||
-                   idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) {
-                       printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d "
-                              "(BIP)\n", sdata->dev->name, idx);
-                       return -EINVAL;
-               }
-       } else if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
-               printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
-                      sdata->dev->name, idx);
-               return -EINVAL;
-       }
-
-       if (remove) {
-               rcu_read_lock();
-
-               err = 0;
-
-               if (is_broadcast_ether_addr(sta_addr)) {
-                       key = sdata->keys[idx];
-               } else {
-                       sta = sta_info_get(local, sta_addr);
-                       if (!sta) {
-                               err = -ENOENT;
-                               goto out_unlock;
-                       }
-                       key = sta->key;
-               }
-
-               ieee80211_key_free(key);
-       } else {
-               key = ieee80211_key_alloc(alg, idx, key_len, _key);
-               if (!key)
-                       return -ENOMEM;
-
-               sta = NULL;
-               err = 0;
-
-               rcu_read_lock();
-
-               if (!is_broadcast_ether_addr(sta_addr)) {
-                       set_tx_key = 0;
-                       /*
-                        * According to the standard, the key index of a
-                        * pairwise key must be zero. However, some AP are
-                        * broken when it comes to WEP key indices, so we
-                        * work around this.
-                        */
-                       if (idx != 0 && alg != ALG_WEP) {
-                               ieee80211_key_free(key);
-                               err = -EINVAL;
-                               goto out_unlock;
-                       }
-
-                       sta = sta_info_get(local, sta_addr);
-                       if (!sta) {
-                               ieee80211_key_free(key);
-                               err = -ENOENT;
-                               goto out_unlock;
-                       }
-               }
-
-               if (alg == ALG_WEP &&
-                       key_len != LEN_WEP40 && key_len != LEN_WEP104) {
-                       ieee80211_key_free(key);
-                       err = -EINVAL;
-                       goto out_unlock;
-               }
-
-               ieee80211_key_link(key, sdata, sta);
-
-               if (set_tx_key || (!sta && !sdata->default_key && key))
-                       ieee80211_set_default_key(sdata, idx);
-               if (alg == ALG_AES_CMAC &&
-                   (set_tx_key || (!sta && !sdata->default_mgmt_key && key)))
-                       ieee80211_set_default_mgmt_key(sdata, idx);
-       }
-
- out_unlock:
-       rcu_read_unlock();
-
-       return err;
-}
-
 static int ieee80211_ioctl_siwgenie(struct net_device *dev,
                                    struct iw_request_info *info,
                                    struct iw_point *data, char *extra)
@@ -131,11 +37,13 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev,
 
        if (sdata->vif.type == NL80211_IFTYPE_STATION) {
                int ret = ieee80211_sta_set_extra_ie(sdata, extra, data->length);
-               if (ret)
+               if (ret && ret != -EALREADY)
                        return ret;
                sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
                sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
-               ieee80211_sta_req_auth(sdata);
+               sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
+               if (ret != -EALREADY)
+                       ieee80211_sta_req_auth(sdata);
                return 0;
        }
 
@@ -185,7 +93,7 @@ static int ieee80211_ioctl_giwfreq(struct net_device *dev,
        if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
                return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
 
-       freq->m = local->hw.conf.channel->center_freq;
+       freq->m = local->oper_channel->center_freq;
        freq->e = 6;
 
        return 0;
@@ -218,6 +126,7 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev,
                        return ret;
 
                sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
+               sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
                ieee80211_sta_req_auth(sdata);
                return 0;
        }
@@ -275,6 +184,7 @@ static int ieee80211_ioctl_siwap(struct net_device *dev,
                if (ret)
                        return ret;
                sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
+               sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
                ieee80211_sta_req_auth(sdata);
                return 0;
        } else if (sdata->vif.type == NL80211_IFTYPE_WDS) {
@@ -396,185 +306,6 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev,
        return 0;
 }
 
-static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
-                                     struct iw_request_info *info,
-                                     union iwreq_data *data, char *extra)
-{
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_channel* chan = local->hw.conf.channel;
-       bool reconf = false;
-       u32 reconf_flags = 0;
-       int new_power_level;
-
-       if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
-               return -EINVAL;
-       if (data->txpower.flags & IW_TXPOW_RANGE)
-               return -EINVAL;
-       if (!chan)
-               return -EINVAL;
-
-       /* only change when not disabling */
-       if (!data->txpower.disabled) {
-               if (data->txpower.fixed) {
-                       if (data->txpower.value < 0)
-                               return -EINVAL;
-                       new_power_level = data->txpower.value;
-                       /*
-                        * Debatable, but we cannot do a fixed power
-                        * level above the regulatory constraint.
-                        * Use "iwconfig wlan0 txpower 15dBm" instead.
-                        */
-                       if (new_power_level > chan->max_power)
-                               return -EINVAL;
-               } else {
-                       /*
-                        * Automatic power level setting, max being the value
-                        * passed in from userland.
-                        */
-                       if (data->txpower.value < 0)
-                               new_power_level = -1;
-                       else
-                               new_power_level = data->txpower.value;
-               }
-
-               reconf = true;
-
-               /*
-                * ieee80211_hw_config() will limit to the channel's
-                * max power and possibly power constraint from AP.
-                */
-               local->user_power_level = new_power_level;
-       }
-
-       if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
-               local->hw.conf.radio_enabled = !(data->txpower.disabled);
-               reconf_flags |= IEEE80211_CONF_CHANGE_RADIO_ENABLED;
-               ieee80211_led_radio(local, local->hw.conf.radio_enabled);
-       }
-
-       if (reconf || reconf_flags)
-               ieee80211_hw_config(local, reconf_flags);
-
-       return 0;
-}
-
-static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
-                                  struct iw_request_info *info,
-                                  union iwreq_data *data, char *extra)
-{
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-
-       data->txpower.fixed = 1;
-       data->txpower.disabled = !(local->hw.conf.radio_enabled);
-       data->txpower.value = local->hw.conf.power_level;
-       data->txpower.flags = IW_TXPOW_DBM;
-
-       return 0;
-}
-
-static int ieee80211_ioctl_siwencode(struct net_device *dev,
-                                    struct iw_request_info *info,
-                                    struct iw_point *erq, char *keybuf)
-{
-       struct ieee80211_sub_if_data *sdata;
-       int idx, i, alg = ALG_WEP;
-       u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-       int remove = 0, ret;
-
-       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-       idx = erq->flags & IW_ENCODE_INDEX;
-       if (idx == 0) {
-               if (sdata->default_key)
-                       for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-                               if (sdata->default_key == sdata->keys[i]) {
-                                       idx = i;
-                                       break;
-                               }
-                       }
-       } else if (idx < 1 || idx > 4)
-               return -EINVAL;
-       else
-               idx--;
-
-       if (erq->flags & IW_ENCODE_DISABLED)
-               remove = 1;
-       else if (erq->length == 0) {
-               /* No key data - just set the default TX key index */
-               ieee80211_set_default_key(sdata, idx);
-               return 0;
-       }
-
-       ret = ieee80211_set_encryption(
-               sdata, bcaddr,
-               idx, alg, remove,
-               !sdata->default_key,
-               keybuf, erq->length);
-
-       if (!ret && sdata->vif.type == NL80211_IFTYPE_STATION) {
-               if (remove)
-                       sdata->u.mgd.flags &= ~IEEE80211_STA_TKIP_WEP_USED;
-               else
-                       sdata->u.mgd.flags |= IEEE80211_STA_TKIP_WEP_USED;
-       }
-
-       return ret;
-}
-
-
-static int ieee80211_ioctl_giwencode(struct net_device *dev,
-                                    struct iw_request_info *info,
-                                    struct iw_point *erq, char *key)
-{
-       struct ieee80211_sub_if_data *sdata;
-       int idx, i;
-
-       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-       idx = erq->flags & IW_ENCODE_INDEX;
-       if (idx < 1 || idx > 4) {
-               idx = -1;
-               if (!sdata->default_key)
-                       idx = 0;
-               else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-                       if (sdata->default_key == sdata->keys[i]) {
-                               idx = i;
-                               break;
-                       }
-               }
-               if (idx < 0)
-                       return -EINVAL;
-       } else
-               idx--;
-
-       erq->flags = idx + 1;
-
-       if (!sdata->keys[idx]) {
-               erq->length = 0;
-               erq->flags |= IW_ENCODE_DISABLED;
-               return 0;
-       }
-
-       memcpy(key, sdata->keys[idx]->conf.key,
-              min_t(int, erq->length, sdata->keys[idx]->conf.keylen));
-       erq->length = sdata->keys[idx]->conf.keylen;
-       erq->flags |= IW_ENCODE_ENABLED;
-
-       if (sdata->vif.type == NL80211_IFTYPE_STATION) {
-               switch (sdata->u.mgd.auth_alg) {
-               case WLAN_AUTH_OPEN:
-               case WLAN_AUTH_LEAP:
-                       erq->flags |= IW_ENCODE_OPEN;
-                       break;
-               case WLAN_AUTH_SHARED_KEY:
-                       erq->flags |= IW_ENCODE_RESTRICTED;
-                       break;
-               }
-       }
-
-       return 0;
-}
-
 static int ieee80211_ioctl_siwpower(struct net_device *dev,
                                    struct iw_request_info *info,
                                    struct iw_param *wrq,
@@ -622,8 +353,7 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev,
        conf->dynamic_ps_timeout = timeout;
 
        if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
-               ieee80211_hw_config(local,
-                                   IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT);
+               ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
 
        ieee80211_recalc_ps(local, -1);
 
@@ -810,82 +540,6 @@ static int ieee80211_ioctl_giwauth(struct net_device *dev,
 }
 
 
-static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
-                                       struct iw_request_info *info,
-                                       struct iw_point *erq, char *extra)
-{
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
-       int uninitialized_var(alg), idx, i, remove = 0;
-
-       switch (ext->alg) {
-       case IW_ENCODE_ALG_NONE:
-               remove = 1;
-               break;
-       case IW_ENCODE_ALG_WEP:
-               alg = ALG_WEP;
-               break;
-       case IW_ENCODE_ALG_TKIP:
-               alg = ALG_TKIP;
-               break;
-       case IW_ENCODE_ALG_CCMP:
-               alg = ALG_CCMP;
-               break;
-       case IW_ENCODE_ALG_AES_CMAC:
-               alg = ALG_AES_CMAC;
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-
-       if (erq->flags & IW_ENCODE_DISABLED)
-               remove = 1;
-
-       idx = erq->flags & IW_ENCODE_INDEX;
-       if (alg == ALG_AES_CMAC) {
-               if (idx < NUM_DEFAULT_KEYS + 1 ||
-                   idx > NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) {
-                       idx = -1;
-                       if (!sdata->default_mgmt_key)
-                               idx = 0;
-                       else for (i = NUM_DEFAULT_KEYS;
-                                 i < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS;
-                                 i++) {
-                               if (sdata->default_mgmt_key == sdata->keys[i])
-                               {
-                                       idx = i;
-                                       break;
-                               }
-                       }
-                       if (idx < 0)
-                               return -EINVAL;
-               } else
-                       idx--;
-       } else {
-               if (idx < 1 || idx > 4) {
-                       idx = -1;
-                       if (!sdata->default_key)
-                               idx = 0;
-                       else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-                               if (sdata->default_key == sdata->keys[i]) {
-                                       idx = i;
-                                       break;
-                               }
-                       }
-                       if (idx < 0)
-                               return -EINVAL;
-               } else
-                       idx--;
-       }
-
-       return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg,
-                                       remove,
-                                       ext->ext_flags &
-                                       IW_ENCODE_EXT_SET_TX_KEY,
-                                       ext->key, ext->key_len);
-}
-
-
 /* Structures to export the Wireless Handlers */
 
 static const iw_handler ieee80211_handler[] =
@@ -928,12 +582,12 @@ static const iw_handler ieee80211_handler[] =
        (iw_handler) cfg80211_wext_giwrts,              /* SIOCGIWRTS */
        (iw_handler) cfg80211_wext_siwfrag,             /* SIOCSIWFRAG */
        (iw_handler) cfg80211_wext_giwfrag,             /* SIOCGIWFRAG */
-       (iw_handler) ieee80211_ioctl_siwtxpower,        /* SIOCSIWTXPOW */
-       (iw_handler) ieee80211_ioctl_giwtxpower,        /* SIOCGIWTXPOW */
+       (iw_handler) cfg80211_wext_siwtxpower,          /* SIOCSIWTXPOW */
+       (iw_handler) cfg80211_wext_giwtxpower,          /* SIOCGIWTXPOW */
        (iw_handler) cfg80211_wext_siwretry,            /* SIOCSIWRETRY */
        (iw_handler) cfg80211_wext_giwretry,            /* SIOCGIWRETRY */
-       (iw_handler) ieee80211_ioctl_siwencode,         /* SIOCSIWENCODE */
-       (iw_handler) ieee80211_ioctl_giwencode,         /* SIOCGIWENCODE */
+       (iw_handler) cfg80211_wext_siwencode,           /* SIOCSIWENCODE */
+       (iw_handler) cfg80211_wext_giwencode,           /* SIOCGIWENCODE */
        (iw_handler) ieee80211_ioctl_siwpower,          /* SIOCSIWPOWER */
        (iw_handler) ieee80211_ioctl_giwpower,          /* SIOCGIWPOWER */
        (iw_handler) NULL,                              /* -- hole -- */
@@ -942,7 +596,7 @@ static const iw_handler ieee80211_handler[] =
        (iw_handler) NULL,                              /* SIOCGIWGENIE */
        (iw_handler) ieee80211_ioctl_siwauth,           /* SIOCSIWAUTH */
        (iw_handler) ieee80211_ioctl_giwauth,           /* SIOCGIWAUTH */
-       (iw_handler) ieee80211_ioctl_siwencodeext,      /* SIOCSIWENCODEEXT */
+       (iw_handler) cfg80211_wext_siwencodeext,        /* SIOCSIWENCODEEXT */
        (iw_handler) NULL,                              /* SIOCGIWENCODEEXT */
        (iw_handler) NULL,                              /* SIOCSIWPMKSA */
        (iw_handler) NULL,                              /* -- hole -- */