#include <linux/kernel.h>
#include <linux/netdevice.h>
+#include <linux/sched.h>
#include <linux/etherdevice.h>
#include <linux/wireless.h>
#include <linux/ieee80211.h>
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)
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);
}
if (key_index == iwm->default_key)
iwm->default_key = -1;
- /* If the interface is down, we just cache this */
- if (!test_bit(IWM_STATUS_READY, &iwm->status))
- return 0;
-
return iwm_set_key(iwm, 1, key);
}
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);
iwm->default_key = key_index;
- /* If the interface is down, we just cache this */
- if (!test_bit(IWM_STATUS_READY, &iwm->status))
- return 0;
-
- ret = iwm_set_tx_key(iwm, key_index);
- if (ret < 0)
- return ret;
-
- return iwm_reset_profile(iwm);
+ return iwm_set_tx_key(iwm, key_index);
}
-int iwm_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
- u8 *mac, struct station_info *sinfo)
+static int iwm_cfg80211_get_station(struct wiphy *wiphy,
+ struct net_device *ndev,
+ u8 *mac, struct station_info *sinfo)
{
struct iwm_priv *iwm = ndev_to_iwm(ndev);
iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode);
- if (iwm->umac_profile_active) {
- int ret = iwm_invalidate_mlme_profile(iwm);
- if (ret < 0)
- IWM_ERR(iwm, "Couldn't invalidate profile\n");
- }
+ if (iwm->umac_profile_active)
+ iwm_invalidate_mlme_profile(iwm);
return 0;
}
static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version)
{
+ IWM_DBG_WEXT(iwm, DBG, "wpa_version: %d\n", wpa_version);
+
if (!wpa_version) {
iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
return 0;
return 0;
}
+ IWM_DBG_WEXT(iwm, DBG, "%ccast cipher is 0x%x\n", ucast ? 'u' : 'm',
+ cipher);
+
switch (cipher) {
case IW_AUTH_CIPHER_NONE:
*profile_cipher = UMAC_CIPHER_TYPE_NONE;
{
struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
struct ieee80211_channel *chan = sme->channel;
+ struct key_params key_param;
int ret;
if (!test_bit(IWM_STATUS_READY, &iwm->status))
if (!sme->ssid)
return -EINVAL;
+ if (iwm->umac_profile_active) {
+ ret = iwm_invalidate_mlme_profile(iwm);
+ if (ret) {
+ IWM_ERR(iwm, "Couldn't invalidate profile\n");
+ return ret;
+ }
+ }
+
if (chan)
iwm->channel =
ieee80211_frequency_to_channel(chan->center_freq);
iwm->umac_profile->bss_num = 0;
}
- ret = iwm_set_auth_type(iwm, sme->auth_type);
+ ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
if (ret < 0)
return ret;
- ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
+ ret = iwm_set_auth_type(iwm, sme->auth_type);
if (ret < 0)
return ret;
return ret;
}
- return iwm_send_mlme_profile(iwm);
+ /*
+ * We save the WEP key in case we want to do shared authentication.
+ * We have to do it so because UMAC will assert whenever it gets a
+ * key before a profile.
+ */
+ if (sme->key) {
+ key_param.key = kmemdup(sme->key, sme->key_len, GFP_KERNEL);
+ if (key_param.key == NULL)
+ return -ENOMEM;
+ key_param.key_len = sme->key_len;
+ key_param.seq_len = 0;
+ key_param.cipher = sme->crypto.ciphers_pairwise[0];
+
+ ret = iwm_key_init(&iwm->keys[sme->key_idx], sme->key_idx,
+ NULL, &key_param);
+ kfree(key_param.key);
+ if (ret < 0) {
+ IWM_ERR(iwm, "Invalid key_params\n");
+ return ret;
+ }
+
+ iwm->default_key = sme->key_idx;
+ }
+
+ ret = iwm_send_mlme_profile(iwm);
+
+ if (iwm->umac_profile->sec.auth_type != UMAC_AUTH_TYPE_LEGACY_PSK ||
+ sme->key == NULL)
+ return ret;
+
+ /*
+ * We want to do shared auth.
+ * We need to actually set the key we previously cached,
+ * and then tell the UMAC it's the default one.
+ * That will trigger the auth+assoc UMAC machinery, and again,
+ * this must be done after setting the profile.
+ */
+ ret = iwm_set_key(iwm, 0, &iwm->keys[sme->key_idx]);
+ if (ret < 0)
+ return ret;
+
+ return iwm_set_tx_key(iwm, iwm->default_key);
}
static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active);
if (iwm->umac_profile_active)
- return iwm_invalidate_mlme_profile(iwm);
+ iwm_invalidate_mlme_profile(iwm);
return 0;
}