iwmc3200wifi: cfg80211 key hooks implemetation
authorSamuel Ortiz <samuel.ortiz@intel.com>
Mon, 15 Jun 2009 19:59:52 +0000 (21:59 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 10 Jul 2009 18:57:51 +0000 (14:57 -0400)
This patch implements the new cfg80211 privacy related hooks: add/get/set_key
and the set_default_key one.
With this implementation we can now call the wext-compat *encode* routines and
reduce our own wext code.

Signed-off-by: Samuel Ortiz <samuel.ortiz@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/iwmc3200wifi/cfg80211.c
drivers/net/wireless/iwmc3200wifi/commands.c
drivers/net/wireless/iwmc3200wifi/commands.h
drivers/net/wireless/iwmc3200wifi/iwm.h
drivers/net/wireless/iwmc3200wifi/main.c
drivers/net/wireless/iwmc3200wifi/wext.c

index bc89b1ef0cade5e6a44bf69980bff63c9d70bfee..739bd9b0ddea15ac63c55ec147ae3a50eee7cbae 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/etherdevice.h>
 #include <linux/wireless.h>
 #include <linux/ieee80211.h>
 #include <net/cfg80211.h>
@@ -130,6 +131,173 @@ static struct ieee80211_supported_band iwm_band_5ghz = {
        .n_bitrates = iwm_a_rates_size,
 };
 
+static int iwm_key_init(struct iwm_key *key, u8 key_index,
+                       const u8 *mac_addr, struct key_params *params)
+{
+       key->hdr.key_idx = key_index;
+       if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
+               key->hdr.multicast = 1;
+               memset(key->hdr.mac, 0xff, ETH_ALEN);
+       } else {
+               key->hdr.multicast = 0;
+               memcpy(key->hdr.mac, mac_addr, ETH_ALEN);
+       }
+
+       if (params) {
+               if (params->key_len > WLAN_MAX_KEY_LEN ||
+                   params->seq_len > IW_ENCODE_SEQ_MAX_SIZE)
+                       return -EINVAL;
+
+               key->cipher = params->cipher;
+               key->key_len = params->key_len;
+               key->seq_len = params->seq_len;
+               memcpy(key->key, params->key, key->key_len);
+               memcpy(key->seq, params->seq, key->seq_len);
+       }
+
+       return 0;
+}
+
+static int iwm_reset_profile(struct iwm_priv *iwm)
+{
+       int ret;
+
+       if (!iwm->umac_profile_active)
+               return 0;
+
+       /*
+        * If there is a current active profile, but no
+        * default key, it's not worth trying to associate again.
+        */
+       if (iwm->default_key < 0)
+               return 0;
+
+       /*
+        * Here we have an active profile, but a key setting changed.
+        * We thus have to invalidate the current profile, and push the
+        * new one. Keys will be pushed when association takes place.
+        */
+       ret = iwm_invalidate_mlme_profile(iwm);
+       if (ret < 0) {
+               IWM_ERR(iwm, "Couldn't invalidate profile\n");
+               return ret;
+       }
+
+       return iwm_send_mlme_profile(iwm);
+}
+
+static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
+                               u8 key_index, const u8 *mac_addr,
+                               struct key_params *params)
+{
+       struct iwm_priv *iwm = ndev_to_iwm(ndev);
+       struct iwm_key *key = &iwm->keys[key_index];
+       int ret;
+
+       IWM_DBG_WEXT(iwm, DBG, "Adding key for %pM\n", mac_addr);
+
+       memset(key, 0, sizeof(struct iwm_key));
+       ret = iwm_key_init(key, key_index, mac_addr, params);
+       if (ret < 0) {
+               IWM_ERR(iwm, "Invalid key_params\n");
+               return ret;
+       }
+
+       /*
+        * The WEP keys can be set before or after setting the essid.
+        * We need to handle both cases by simply pushing the keys after
+        * we send the profile.
+        * If the profile is not set yet (i.e. we're pushing keys before
+        * the essid), we set the cipher appropriately.
+        * If the profile is set, we havent associated yet because our
+        * cipher was incorrectly set. So we invalidate and send the
+        * profile again.
+        */
+       if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+           key->cipher == WLAN_CIPHER_SUITE_WEP104) {
+               u8 *ucast_cipher = &iwm->umac_profile->sec.ucast_cipher;
+               u8 *mcast_cipher = &iwm->umac_profile->sec.mcast_cipher;
+
+               IWM_DBG_WEXT(iwm, DBG, "WEP key\n");
+
+               if (key->cipher == WLAN_CIPHER_SUITE_WEP40)
+                       *ucast_cipher = *mcast_cipher = UMAC_CIPHER_TYPE_WEP_40;
+               if (key->cipher == WLAN_CIPHER_SUITE_WEP104)
+                       *ucast_cipher = *mcast_cipher =
+                               UMAC_CIPHER_TYPE_WEP_104;
+
+               return iwm_reset_profile(iwm);
+       }
+
+       return iwm_set_key(iwm, 0, key);
+}
+
+static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
+                               u8 key_index, const u8 *mac_addr, void *cookie,
+                               void (*callback)(void *cookie,
+                                                struct key_params*))
+{
+       struct iwm_priv *iwm = ndev_to_iwm(ndev);
+       struct iwm_key *key = &iwm->keys[key_index];
+       struct key_params params;
+
+       IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index);
+
+       memset(&params, 0, sizeof(params));
+
+       params.cipher = key->cipher;
+       params.key_len = key->key_len;
+       params.seq_len = key->seq_len;
+       params.seq = key->seq;
+       params.key = key->key;
+
+       callback(cookie, &params);
+
+       return key->key_len ? 0 : -ENOENT;
+}
+
+
+static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
+                               u8 key_index, const u8 *mac_addr)
+{
+       struct iwm_priv *iwm = ndev_to_iwm(ndev);
+       struct iwm_key *key = &iwm->keys[key_index];
+
+       if (!iwm->keys[key_index].key_len) {
+               IWM_DBG_WEXT(iwm, DBG, "Key %d not used\n", key_index);
+               return 0;
+       }
+
+       if (key_index == iwm->default_key)
+               iwm->default_key = -1;
+
+       return iwm_set_key(iwm, 1, key);
+}
+
+static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
+                                       struct net_device *ndev,
+                                       u8 key_index)
+{
+       struct iwm_priv *iwm = ndev_to_iwm(ndev);
+       int ret;
+
+       IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index);
+
+       if (!iwm->keys[key_index].key_len) {
+               IWM_ERR(iwm, "Key %d not used\n", key_index);
+               return -EINVAL;
+       }
+
+       ret = iwm_set_tx_key(iwm, key_index);
+       if (ret < 0)
+               return ret;
+
+       iwm->default_key = key_index;
+
+       return iwm_reset_profile(iwm);
+}
+
+
 int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
 {
        struct wiphy *wiphy = iwm_to_wiphy(iwm);
@@ -326,6 +494,10 @@ static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 
 static struct cfg80211_ops iwm_cfg80211_ops = {
        .change_virtual_intf = iwm_cfg80211_change_iface,
+       .add_key = iwm_cfg80211_add_key,
+       .get_key = iwm_cfg80211_get_key,
+       .del_key = iwm_cfg80211_del_key,
+       .set_default_key = iwm_cfg80211_set_default_key,
        .scan = iwm_cfg80211_scan,
        .set_wiphy_params = iwm_cfg80211_set_wiphy_params,
        .join_ibss = iwm_cfg80211_join_ibss,
index 337a884f52df873700e0cbd62215abc6bde8302a..145f6f5ae7479ed4cef61b6de2cea718dbcf7586 100644 (file)
@@ -524,9 +524,6 @@ int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx)
 {
        struct iwm_umac_tx_key_id tx_key_id;
 
-       if (!iwm->default_key || !iwm->default_key->in_use)
-               return -EINVAL;
-
        tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID;
        tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) -
                                             sizeof(struct iwm_umac_wifi_if));
@@ -569,10 +566,9 @@ static int iwm_check_profile(struct iwm_priv *iwm)
        return 0;
 }
 
-int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
-               struct iwm_key *key)
+int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key)
 {
-       int ret;
+       int ret = 0;
        u8 cmd[64], *sta_addr, *key_data, key_len;
        s8 key_idx;
        u16 cmd_size = 0;
@@ -582,9 +578,6 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
        struct iwm_umac_key_tkip *tkip = (struct iwm_umac_key_tkip *)cmd;
        struct iwm_umac_key_ccmp *ccmp = (struct iwm_umac_key_ccmp *)cmd;
 
-       if (set_tx_key)
-               iwm->default_key = key;
-
        /*
         * We check if our current profile is valid.
         * If not, we dont push the key, we just cache them,
@@ -603,8 +596,7 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
        key_idx = key->hdr.key_idx;
 
        if (!remove) {
-               IWM_DBG_WEXT(iwm, DBG, "key_idx:%d set tx key:%d\n",
-                            key_idx, set_tx_key);
+               IWM_DBG_WEXT(iwm, DBG, "key_idx:%d\n", key_idx);
                IWM_DBG_WEXT(iwm, DBG, "key_len:%d\n", key_len);
                IWM_DBG_WEXT(iwm, DBG, "MAC:%pM, idx:%d, multicast:%d\n",
                       key_hdr->mac, key_hdr->key_idx, key_hdr->multicast);
@@ -616,8 +608,8 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
                             iwm->umac_profile->sec.auth_type,
                             iwm->umac_profile->sec.flags);
 
-               switch (key->alg) {
-               case UMAC_CIPHER_TYPE_WEP_40:
+               switch (key->cipher) {
+               case WLAN_CIPHER_SUITE_WEP40:
                        wep40->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP40_KEY;
                        wep40->hdr.buf_size =
                                cpu_to_le16(sizeof(struct iwm_umac_key_wep40) -
@@ -631,7 +623,7 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
                        cmd_size = sizeof(struct iwm_umac_key_wep40);
                        break;
 
-               case UMAC_CIPHER_TYPE_WEP_104:
+               case WLAN_CIPHER_SUITE_WEP104:
                        wep104->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP104_KEY;
                        wep104->hdr.buf_size =
                                cpu_to_le16(sizeof(struct iwm_umac_key_wep104) -
@@ -645,7 +637,7 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
                        cmd_size = sizeof(struct iwm_umac_key_wep104);
                        break;
 
-               case UMAC_CIPHER_TYPE_CCMP:
+               case WLAN_CIPHER_SUITE_CCMP:
                        key_hdr->key_idx++;
                        ccmp->hdr.oid = UMAC_WIFI_IF_CMD_ADD_CCMP_KEY;
                        ccmp->hdr.buf_size =
@@ -657,13 +649,13 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
 
                        memcpy(ccmp->key, key_data, key_len);
 
-                       if (key->flags & IW_ENCODE_EXT_RX_SEQ_VALID)
-                               memcpy(ccmp->iv_count, key->rx_seq, 6);
+                       if (key->seq_len)
+                               memcpy(ccmp->iv_count, key->seq, key->seq_len);
 
                        cmd_size = sizeof(struct iwm_umac_key_ccmp);
                        break;
 
-               case UMAC_CIPHER_TYPE_TKIP:
+               case WLAN_CIPHER_SUITE_TKIP:
                        key_hdr->key_idx++;
                        tkip->hdr.oid = UMAC_WIFI_IF_CMD_ADD_TKIP_KEY;
                        tkip->hdr.buf_size =
@@ -680,8 +672,8 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
                               key_data + IWM_TKIP_KEY_SIZE + IWM_TKIP_MIC_SIZE,
                               IWM_TKIP_MIC_SIZE);
 
-                       if (key->flags & IW_ENCODE_EXT_RX_SEQ_VALID)
-                               memcpy(ccmp->iv_count, key->rx_seq, 6);
+                       if (key->seq_len)
+                               memcpy(ccmp->iv_count, key->seq, key->seq_len);
 
                        cmd_size = sizeof(struct iwm_umac_key_tkip);
                        break;
@@ -690,8 +682,8 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
                        return -ENOTSUPP;
                }
 
-               if ((key->alg == UMAC_CIPHER_TYPE_CCMP) ||
-                   (key->alg == UMAC_CIPHER_TYPE_TKIP))
+               if ((key->cipher == WLAN_CIPHER_SUITE_TKIP) ||
+                   (key->cipher == WLAN_CIPHER_SUITE_CCMP))
                        /*
                         * UGLY_UGLY_UGLY
                         * Copied HACK from the MWG driver.
@@ -702,23 +694,11 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
                        schedule_timeout_interruptible(usecs_to_jiffies(300));
 
                ret =  iwm_send_wifi_if_cmd(iwm, cmd, cmd_size, 1);
-               if (ret < 0)
-                       goto err;
-
-               /*
-                * We need a default key only if it is set and
-                * if we're doing WEP.
-                */
-               if (iwm->default_key == key &&
-                       ((key->alg == UMAC_CIPHER_TYPE_WEP_40) ||
-                        (key->alg == UMAC_CIPHER_TYPE_WEP_104))) {
-                       ret = iwm_set_tx_key(iwm, key_idx);
-                       if (ret < 0)
-                               goto err;
-               }
        } else {
                struct iwm_umac_key_remove key_remove;
 
+               IWM_DBG_WEXT(iwm, ERR, "Removing key_idx:%d\n", key_idx);
+
                key_remove.hdr.oid = UMAC_WIFI_IF_CMD_REMOVE_KEY;
                key_remove.hdr.buf_size =
                        cpu_to_le16(sizeof(struct iwm_umac_key_remove) -
@@ -732,13 +712,9 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
                if (ret < 0)
                        return ret;
 
-               iwm->keys[key_idx].in_use = 0;
+               iwm->keys[key_idx].key_len = 0;
        }
 
-       return 0;
-
- err:
-       kfree(key);
        return ret;
 }
 
@@ -761,22 +737,24 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm)
        }
 
        for (i = 0; i < IWM_NUM_KEYS; i++)
-               if (iwm->keys[i].in_use) {
-                       int default_key = 0;
+               if (iwm->keys[i].key_len) {
                        struct iwm_key *key = &iwm->keys[i];
 
-                       if (key == iwm->default_key)
-                               default_key = 1;
-
                        /* Wait for the profile before sending the keys */
                        wait_event_interruptible_timeout(iwm->mlme_queue,
                             (test_bit(IWM_STATUS_ASSOCIATING, &iwm->status) ||
                              test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)),
                                                         3 * HZ);
 
-                       ret = iwm_set_key(iwm, 0, default_key, key);
+                       ret = iwm_set_key(iwm, 0, key);
                        if (ret < 0)
                                return ret;
+
+                       if (iwm->default_key == i) {
+                               ret = iwm_set_tx_key(iwm, i);
+                               if (ret < 0)
+                                       return ret;
+                       }
                }
 
        return 0;
index 36b13a1305956973883de78d9db38426e2b3d268..3510df8ff391194c788b1b6f84f0dcf7090a38e4 100644 (file)
@@ -406,8 +406,7 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm);
 int iwm_invalidate_mlme_profile(struct iwm_priv *iwm);
 int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id);
 int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx);
-int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
-               struct iwm_key *key);
+int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key);
 int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags);
 int iwm_send_umac_channel_list(struct iwm_priv *iwm);
 int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids,
index d8d4ae2d91b0abf31d306b1840f01e54e6b82500..90b05d99963574f64cf919205f127b090193a7b9 100644 (file)
@@ -162,13 +162,11 @@ struct iwm_umac_key_hdr {
 
 struct iwm_key {
        struct iwm_umac_key_hdr hdr;
-       u8 in_use;
-       u8 alg;
-       u32 flags;
-       u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE];
-       u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE];
-       u8 key_len;
-       u8 key[32];
+       u32 cipher;
+       u8 key[WLAN_MAX_KEY_LEN];
+       u8 seq[IW_ENCODE_SEQ_MAX_SIZE];
+       int key_len;
+       int seq_len;
 };
 
 #define IWM_RX_ID_HASH  0xff
@@ -276,7 +274,7 @@ struct iwm_priv {
        struct iwm_tx_queue txq[IWM_TX_QUEUES];
 
        struct iwm_key keys[IWM_NUM_KEYS];
-       struct iwm_key *default_key;
+       sdefault_key;
 
        DECLARE_BITMAP(wifi_ntfy, WIFI_IF_NTFY_MAX);
        wait_queue_head_t wifi_ntfy_queue;
index 844872213a122a12837df5eaee9d358fb29dde41..7f56c06a53db84787bde98e3111e8aa67a4f3cfb 100644 (file)
@@ -230,7 +230,7 @@ int iwm_priv_init(struct iwm_priv *iwm)
        for (i = 0; i < IWM_NUM_KEYS; i++)
                memset(&iwm->keys[i], 0, sizeof(struct iwm_key));
 
-       iwm->default_key = NULL;
+       iwm->default_key = -1;
 
        init_timer(&iwm->watchdog);
        iwm->watchdog.function = iwm_watchdog;
@@ -709,7 +709,7 @@ int __iwm_down(struct iwm_priv *iwm)
        iwm->umac_profile = NULL;
        iwm_bss_list_clean(iwm);
 
-       iwm->default_key = NULL;
+       iwm->default_key = -1;
        iwm->core_enabled = 0;
 
        ret = iwm_bus_disable(iwm);
index 889194931b4ed0388b719eb0fc7781db4210475a..3062f37bbe95a72f7e6582d5ff13b44f90aee93f 100644 (file)
@@ -84,6 +84,8 @@ static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info,
        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)
                return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
 
@@ -116,8 +118,7 @@ static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info,
                 */
                if (is_zero_ether_addr(ap_addr->sa_data)) {
                        for (i = 0; i < IWM_NUM_KEYS; i++)
-                               iwm->keys[i].in_use = 0;
-
+                               iwm->keys[i].key_len = 0;
                }
 
                ret = iwm_invalidate_mlme_profile(iwm);
@@ -163,6 +164,8 @@ static int iwm_wext_siwessid(struct net_device *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)
                return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
 
@@ -212,27 +215,6 @@ static int iwm_wext_giwessid(struct net_device *dev,
        return 0;
 }
 
-static struct iwm_key *
-iwm_key_init(struct iwm_priv *iwm, u8 key_idx, bool in_use,
-            struct iw_encode_ext *ext, u8 alg)
-{
-       struct iwm_key *key = &iwm->keys[key_idx];
-
-       memset(key, 0, sizeof(struct iwm_key));
-       memcpy(key->hdr.mac, ext->addr.sa_data, ETH_ALEN);
-       key->hdr.key_idx = key_idx;
-       if (is_broadcast_ether_addr(ext->addr.sa_data))
-               key->hdr.multicast = 1;
-
-       key->in_use = in_use;
-       key->flags = ext->ext_flags;
-       key->alg = alg;
-       key->key_len = ext->key_len;
-       memcpy(key->key, ext->key, ext->key_len);
-
-       return key;
-}
-
 static int iwm_wext_giwrate(struct net_device *dev,
                            struct iw_request_info *info,
                            struct iw_param *rate, char *extra)
@@ -244,184 +226,6 @@ static int iwm_wext_giwrate(struct net_device *dev,
        return 0;
 }
 
-static int iwm_wext_siwencode(struct net_device *dev,
-                             struct iw_request_info *info,
-                             struct iw_point *erq, char *key_buf)
-{
-       struct iwm_priv *iwm = ndev_to_iwm(dev);
-       struct iwm_key *uninitialized_var(key);
-       int idx, i, uninitialized_var(alg), remove = 0, ret;
-
-       IWM_DBG_WEXT(iwm, DBG, "key len: %d\n", erq->length);
-       IWM_DBG_WEXT(iwm, DBG, "flags: 0x%x\n", erq->flags);
-
-       if (!iwm->umac_profile) {
-               IWM_ERR(iwm, "UMAC profile not allocated yet\n");
-               return -ENODEV;
-       }
-
-       if (erq->length == WLAN_KEY_LEN_WEP40) {
-               alg = UMAC_CIPHER_TYPE_WEP_40;
-               iwm->umac_profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_WEP_40;
-               iwm->umac_profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_WEP_40;
-       } else if (erq->length == WLAN_KEY_LEN_WEP104) {
-               alg = UMAC_CIPHER_TYPE_WEP_104;
-               iwm->umac_profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_WEP_104;
-               iwm->umac_profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_WEP_104;
-       }
-
-       if (erq->flags & IW_ENCODE_RESTRICTED)
-               iwm->umac_profile->sec.auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
-       else
-               iwm->umac_profile->sec.auth_type = UMAC_AUTH_TYPE_OPEN;
-
-       idx = erq->flags & IW_ENCODE_INDEX;
-       if (idx == 0) {
-               if (iwm->default_key)
-                       for (i = 0; i < IWM_NUM_KEYS; i++) {
-                               if (iwm->default_key == &iwm->keys[i]) {
-                                       idx = i;
-                                       break;
-                               }
-                       }
-               else
-                       iwm->default_key = &iwm->keys[idx];
-       } else if (idx < 1 || idx > 4) {
-               return -EINVAL;
-       } else
-               idx--;
-
-       if (erq->flags & IW_ENCODE_DISABLED)
-               remove = 1;
-       else if (erq->length == 0) {
-               if (!iwm->keys[idx].in_use)
-                       return -EINVAL;
-               iwm->default_key = &iwm->keys[idx];
-       }
-
-       if (erq->length) {
-               key = &iwm->keys[idx];
-               memset(key, 0, sizeof(struct iwm_key));
-               memset(key->hdr.mac, 0xff, ETH_ALEN);
-               key->hdr.key_idx = idx;
-               key->hdr.multicast = 1;
-               key->in_use = !remove;
-               key->alg = alg;
-               key->key_len = erq->length;
-               memcpy(key->key, key_buf, erq->length);
-
-               IWM_DBG_WEXT(iwm, DBG, "Setting key %d, default: %d\n",
-                            idx, !!iwm->default_key);
-       }
-
-       if (remove) {
-               if ((erq->flags & IW_ENCODE_NOKEY) || (erq->length == 0)) {
-                       int j;
-                       for (j = 0; j < IWM_NUM_KEYS; j++)
-                               if (iwm->keys[j].in_use) {
-                                       struct iwm_key *k = &iwm->keys[j];
-
-                                       k->in_use = 0;
-                                       ret = iwm_set_key(iwm, remove, 0, k);
-                                       if (ret < 0)
-                                               return ret;
-                               }
-
-                       iwm->umac_profile->sec.ucast_cipher =
-                                                       UMAC_CIPHER_TYPE_NONE;
-                       iwm->umac_profile->sec.mcast_cipher =
-                                                       UMAC_CIPHER_TYPE_NONE;
-                       iwm->umac_profile->sec.auth_type =
-                                                       UMAC_AUTH_TYPE_OPEN;
-
-                       return 0;
-               } else {
-                       key->in_use = 0;
-                       return iwm_set_key(iwm, remove, 0, key);
-               }
-       }
-
-       /*
-        * If we havent set a profile yet, we cant set keys.
-        * Keys will be pushed after we're associated.
-        */
-       if (!iwm->umac_profile_active)
-               return 0;
-
-       /*
-        * If there is a current active profile, but no
-        * default key, it's not worth trying to associate again.
-        */
-       if (!iwm->default_key)
-               return 0;
-
-       /*
-        * Here we have an active profile, but a key setting changed.
-        * We thus have to invalidate the current profile, and push the
-        * new one. Keys will be pushed when association takes place.
-        */
-       ret = iwm_invalidate_mlme_profile(iwm);
-       if (ret < 0) {
-               IWM_ERR(iwm, "Couldn't invalidate profile\n");
-               return ret;
-       }
-
-       return iwm_send_mlme_profile(iwm);
-}
-
-static int iwm_wext_giwencode(struct net_device *dev,
-                             struct iw_request_info *info,
-                             struct iw_point *erq, char *key)
-{
-       struct iwm_priv *iwm = ndev_to_iwm(dev);
-       int idx, i;
-
-       idx = erq->flags & IW_ENCODE_INDEX;
-       if (idx < 1 || idx > 4) {
-               idx = -1;
-               if (!iwm->default_key) {
-                       erq->length = 0;
-                       erq->flags |= IW_ENCODE_NOKEY;
-                       return 0;
-               } else
-                       for (i = 0; i < IWM_NUM_KEYS; i++) {
-                               if (iwm->default_key == &iwm->keys[i]) {
-                                       idx = i;
-                                       break;
-                               }
-                       }
-               if (idx < 0)
-                       return -EINVAL;
-       } else
-               idx--;
-
-       erq->flags = idx + 1;
-
-       if (!iwm->keys[idx].in_use) {
-               erq->length = 0;
-               erq->flags |= IW_ENCODE_DISABLED;
-               return 0;
-       }
-
-       memcpy(key, iwm->keys[idx].key,
-              min_t(int, erq->length, iwm->keys[idx].key_len));
-       erq->length = iwm->keys[idx].key_len;
-       erq->flags |= IW_ENCODE_ENABLED;
-
-       if (iwm->umac_profile->mode == UMAC_MODE_BSS) {
-               switch (iwm->umac_profile->sec.auth_type) {
-               case UMAC_AUTH_TYPE_OPEN:
-                       erq->flags |= IW_ENCODE_OPEN;
-                       break;
-               default:
-                       erq->flags |= IW_ENCODE_RESTRICTED;
-                       break;
-               }
-       }
-
-       return 0;
-}
-
 static int iwm_set_wpa_version(struct iwm_priv *iwm, u8 wpa_version)
 {
        if (wpa_version & IW_AUTH_WPA_VERSION_WPA2)
@@ -481,6 +285,8 @@ 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) {
@@ -530,6 +336,8 @@ 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;
@@ -541,6 +349,7 @@ static int iwm_set_auth_alg(struct iwm_priv *iwm, u8 auth_alg)
                                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;
@@ -603,75 +412,6 @@ static int iwm_wext_giwauth(struct net_device *dev,
        return 0;
 }
 
-static int iwm_wext_siwencodeext(struct net_device *dev,
-                                struct iw_request_info *info,
-                                struct iw_point *erq, char *extra)
-{
-       struct iwm_priv *iwm = ndev_to_iwm(dev);
-       struct iwm_key *key;
-       struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
-       int uninitialized_var(alg), idx, i, remove = 0;
-
-       IWM_DBG_WEXT(iwm, DBG, "alg: 0x%x\n", ext->alg);
-       IWM_DBG_WEXT(iwm, DBG, "key len: %d\n", ext->key_len);
-       IWM_DBG_WEXT(iwm, DBG, "ext_flags: 0x%x\n", ext->ext_flags);
-       IWM_DBG_WEXT(iwm, DBG, "flags: 0x%x\n", erq->flags);
-       IWM_DBG_WEXT(iwm, DBG, "length: 0x%x\n", erq->length);
-
-       switch (ext->alg) {
-       case IW_ENCODE_ALG_NONE:
-               remove = 1;
-               break;
-       case IW_ENCODE_ALG_WEP:
-               if (ext->key_len == WLAN_KEY_LEN_WEP40)
-                       alg = UMAC_CIPHER_TYPE_WEP_40;
-               else if (ext->key_len == WLAN_KEY_LEN_WEP104)
-                       alg = UMAC_CIPHER_TYPE_WEP_104;
-               else {
-                       IWM_ERR(iwm, "Invalid key length: %d\n", ext->key_len);
-                       return -EINVAL;
-               }
-
-               break;
-       case IW_ENCODE_ALG_TKIP:
-               alg = UMAC_CIPHER_TYPE_TKIP;
-               break;
-       case IW_ENCODE_ALG_CCMP:
-               alg = UMAC_CIPHER_TYPE_CCMP;
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-
-       idx = erq->flags & IW_ENCODE_INDEX;
-
-       if (idx == 0) {
-               if (iwm->default_key)
-                       for (i = 0; i < IWM_NUM_KEYS; i++) {
-                               if (iwm->default_key == &iwm->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) ||
-                (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) {
-               iwm->default_key = &iwm->keys[idx];
-               if (iwm->umac_profile_active && ext->alg == IW_ENCODE_ALG_WEP)
-                       return iwm_set_tx_key(iwm, idx);
-       }
-
-       key = iwm_key_init(iwm, idx, !remove, ext, alg);
-
-       return iwm_set_key(iwm, remove, !iwm->default_key, key);
-}
-
 static const iw_handler iwm_handlers[] =
 {
        (iw_handler) NULL,                              /* SIOCSIWCOMMIT */
@@ -716,8 +456,8 @@ static const iw_handler iwm_handlers[] =
        (iw_handler) NULL,                              /* SIOCGIWTXPOW */
        (iw_handler) NULL,                              /* SIOCSIWRETRY */
        (iw_handler) NULL,                              /* SIOCGIWRETRY */
-       (iw_handler) iwm_wext_siwencode,                /* SIOCSIWENCODE */
-       (iw_handler) iwm_wext_giwencode,                /* SIOCGIWENCODE */
+       (iw_handler) cfg80211_wext_siwencode,           /* SIOCSIWENCODE */
+       (iw_handler) cfg80211_wext_giwencode,           /* SIOCGIWENCODE */
        (iw_handler) iwm_wext_siwpower,                 /* SIOCSIWPOWER */
        (iw_handler) iwm_wext_giwpower,                 /* SIOCGIWPOWER */
        (iw_handler) NULL,                              /* -- hole -- */
@@ -726,7 +466,7 @@ static const iw_handler iwm_handlers[] =
        (iw_handler) NULL,                              /* SIOCGIWGENIE */
        (iw_handler) iwm_wext_siwauth,                  /* SIOCSIWAUTH */
        (iw_handler) iwm_wext_giwauth,                  /* SIOCGIWAUTH */
-       (iw_handler) iwm_wext_siwencodeext,             /* SIOCSIWENCODEEXT */
+       (iw_handler) cfg80211_wext_siwencodeext,        /* SIOCSIWENCODEEXT */
        (iw_handler) NULL,                              /* SIOCGIWENCODEEXT */
        (iw_handler) NULL,                              /* SIOCSIWPMKSA */
        (iw_handler) NULL,                              /* -- hole -- */