diff options
author | Javier Cardona <javier@cozybit.com> | 2008-11-06 16:04:44 -0800 |
---|---|---|
committer | Deepak Saxena <dsaxena@laptop.org> | 2008-11-11 12:10:26 -0800 |
commit | 4c4cb9ac0f7373d092cbe6b9ad58e324c6a5647b (patch) | |
tree | 7d98d99f9252f175d9506a4d2241e7950131c888 | |
parent | fd3ef663a9b2729a6f626326d6692fc77323f11d (diff) | |
download | lwn-4c4cb9ac0f7373d092cbe6b9ad58e324c6a5647b.tar.gz lwn-4c4cb9ac0f7373d092cbe6b9ad58e324c6a5647b.zip |
libertas: Decouple RSN enable/disable from WPA key installation.
Signed-off-by: Javier Cardona <javier@cozybit.com>
-rw-r--r-- | drivers/net/wireless/libertas/assoc.c | 52 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/cmd.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/defs.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/dev.h | 13 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/main.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/wext.c | 64 |
6 files changed, 35 insertions, 113 deletions
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 2238e0412858..6cf6a23a882c 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -343,41 +343,6 @@ out: } -static int assoc_helper_wpa_keys(struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0; - unsigned int flags = assoc_req->flags; - - lbs_deb_enter(LBS_DEB_ASSOC); - - /* Work around older firmware bug where WPA unicast and multicast - * keys must be set independently. Seen in SDIO parts with firmware - * version 5.0.11p0. - */ - - if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { - clear_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags); - ret = lbs_set_key_material(priv, &assoc_req->wpa_unicast_key); - assoc_req->flags = flags; - } - - if (ret) - goto out; - - if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) { - clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags); - - ret = lbs_set_key_material(priv, &assoc_req->wpa_mcast_key); - assoc_req->flags = flags; - } - -out: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - - static int assoc_helper_wpa_ie(struct lbs_private *priv, struct assoc_request * assoc_req) { @@ -605,13 +570,6 @@ void lbs_association_worker(struct work_struct *work) goto out; } - if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags) - || test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { - ret = assoc_helper_wpa_keys(priv, assoc_req); - if (ret) - goto out; - } - /* SSID/BSSID should be the _last_ config option set, because they * trigger the association attempt. */ @@ -718,16 +676,6 @@ struct assoc_request *lbs_get_association_request(struct lbs_private *priv) if (!test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) assoc_req->wep_tx_keyidx = priv->wep_tx_keyidx; - if (!test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) { - memcpy(&assoc_req->wpa_mcast_key, &priv->wpa_mcast_key, - sizeof(struct enc_key)); - } - - if (!test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { - memcpy(&assoc_req->wpa_unicast_key, &priv->wpa_unicast_key, - sizeof(struct enc_key)); - } - if (!test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { memcpy(&assoc_req->secinfo, &priv->secinfo, sizeof(struct lbs_802_11_security)); diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 10ec0905befe..5b5ef6085972 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -444,10 +444,15 @@ int lbs_set_key_material(struct lbs_private *priv, struct enc_key *key) if (ret) goto out; + key->flags |= KEY_INFO_WPA_INSTALLED; if (key->flags & KEY_INFO_WPA_ENABLED) lbs_deb_cmd("SET_WPA_KEY: %s%s installed\n", key->flags & KEY_INFO_WPA_UNICAST ? "PTK" : "", key->flags & KEY_INFO_WPA_MCAST ? "GTK" : ""); + else + lbs_deb_cmd("SET_WPA_KEY: %s%s cleared\n", + key->flags & KEY_INFO_WPA_UNICAST ? "PTK" : "", + key->flags & KEY_INFO_WPA_MCAST ? "GTK" : ""); out: lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index 98c5dff632fb..8de989fb5ff2 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h @@ -386,7 +386,8 @@ enum KEY_TYPE_ID { enum KEY_INFO_WPA { KEY_INFO_WPA_MCAST = 0x01, KEY_INFO_WPA_UNICAST = 0x02, - KEY_INFO_WPA_ENABLED = 0x04 + KEY_INFO_WPA_ENABLED = 0x04, + KEY_INFO_WPA_INSTALLED = 0x08 }; /** SNMP_MIB_VALUE_e */ diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 0c07a0b2f221..c4e3d29dcc37 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -143,7 +143,8 @@ struct lbs_private { wait_queue_head_t waitq; struct workqueue_struct *work_thread; - struct work_struct mcast_work; + struct work_struct mcast_work; + struct work_struct wpa_key_work; struct delayed_work scan_work; struct delayed_work assoc_work; @@ -340,10 +341,8 @@ struct assoc_request { #define ASSOC_FLAG_BSSID 5 #define ASSOC_FLAG_WEP_KEYS 6 #define ASSOC_FLAG_WEP_TX_KEYIDX 7 -#define ASSOC_FLAG_WPA_MCAST_KEY 8 -#define ASSOC_FLAG_WPA_UCAST_KEY 9 -#define ASSOC_FLAG_SECINFO 10 -#define ASSOC_FLAG_WPA_IE 11 +#define ASSOC_FLAG_SECINFO 8 +#define ASSOC_FLAG_WPA_IE 9 unsigned long flags; u8 ssid[IW_ESSID_MAX_SIZE + 1]; @@ -357,10 +356,6 @@ struct assoc_request { struct enc_key wep_keys[4]; u16 wep_tx_keyidx; - /** WPA keys */ - struct enc_key wpa_mcast_key; - struct enc_key wpa_unicast_key; - struct lbs_802_11_security secinfo; /** WPA Information Elements*/ diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 6ccd395d0972..37a5fc43ab28 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -622,6 +622,16 @@ static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd, return i; } +static void wpa_key_worker(struct work_struct *work) +{ + struct lbs_private *priv = + container_of(work, struct lbs_private, wpa_key_work); + if (!(priv->wpa_mcast_key.flags & KEY_INFO_WPA_INSTALLED)) + lbs_set_key_material(priv, &priv->wpa_mcast_key); + else if (!(priv->wpa_unicast_key.flags & KEY_INFO_WPA_INSTALLED)) + lbs_set_key_material(priv, &priv->wpa_unicast_key); +} + static void lbs_set_mcast_worker(struct work_struct *work) { struct lbs_private *priv = container_of(work, struct lbs_private, mcast_work); @@ -1176,6 +1186,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); INIT_WORK(&priv->sync_channel, lbs_sync_channel); + INIT_WORK(&priv->wpa_key_work, wpa_key_worker); sprintf(priv->mesh_ssid, "mesh"); priv->mesh_ssid_len = 4; diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 0a27dbef48cb..3df9dc57f8b9 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -30,6 +30,13 @@ static inline void lbs_postpone_association_work(struct lbs_private *priv) queue_delayed_work(priv->work_thread, &priv->assoc_work, HZ / 2); } +static inline void lbs_schedule_wpa_key_work(struct lbs_private *priv) +{ + if (priv->surpriseremoved) + return; + queue_work(priv->work_thread, &priv->wpa_key_work); +} + static inline void lbs_cancel_association_work(struct lbs_private *priv) { cancel_delayed_work(&priv->assoc_work); @@ -1294,14 +1301,6 @@ static void disable_wpa(struct assoc_request *assoc_req) { lbs_deb_enter(LBS_DEB_WEXT); - memset(&assoc_req->wpa_mcast_key, 0, sizeof (struct enc_key)); - assoc_req->wpa_mcast_key.flags = KEY_INFO_WPA_MCAST; - set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags); - - memset(&assoc_req->wpa_unicast_key, 0, sizeof (struct enc_key)); - assoc_req->wpa_unicast_key.flags = KEY_INFO_WPA_UNICAST; - set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags); - assoc_req->secinfo.WPAenabled = 0; assoc_req->secinfo.WPA2enabled = 0; set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); @@ -1490,42 +1489,6 @@ out: return ret; } -/* - * WPA requires key installation to happen immediately after - * the 4-way handshake. We cannot defer key installation to - * the association worker. - * */ -static int install_wpa_key_now(struct lbs_private *priv, struct enc_key *pkey) -{ - int ret = 0; - uint16_t rsn = 0; - - /* disable_wep() does a proper WEP key removal, but it is deferred. - Here we just do the minimal necessary so we can successfully install - the WPA key. - */ - if (priv->mac_control & CMD_ACT_MAC_WEP_ENABLE) { - struct assoc_request ignored; - lbs_cmd_802_11_set_wep(priv, CMD_ACT_REMOVE, &ignored); - priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE; - lbs_set_mac_control(priv); - } - - - /* Get RSN disabled/enabled, in failure assume it's off */ - lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_GET, &rsn); - - if (!rsn) { /* Enable rsn only if needed */ - rsn = !rsn; - ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_SET, &rsn); - } - - if (!ret) - ret = lbs_set_key_material(priv, pkey); - - return ret; -} - /** * @brief Set Encryption key Extended (WPA/802.1x and WEP) * @@ -1557,7 +1520,9 @@ static int lbs_set_encodeext(struct net_device *dev, if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) { disable_wep (assoc_req); - disable_wpa (assoc_req); + memset(&priv->wpa_mcast_key, 0, sizeof(struct enc_key)); + memset(&priv->wpa_unicast_key, 0, sizeof(struct enc_key)); + lbs_schedule_wpa_key_work(priv); } else if (alg == IW_ENCODE_ALG_WEP) { u16 is_default = 0, index, set_tx_key = 0; @@ -1610,9 +1575,9 @@ static int lbs_set_encodeext(struct net_device *dev, } if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { - pkey = &assoc_req->wpa_mcast_key; + pkey = &priv->wpa_mcast_key; } else { - pkey = &assoc_req->wpa_unicast_key; + pkey = &priv->wpa_unicast_key; } memset(pkey, 0, sizeof (struct enc_key)); @@ -1642,10 +1607,7 @@ static int lbs_set_encodeext(struct net_device *dev, } disable_wep(assoc_req); - mutex_unlock(&priv->lock); - ret = install_wpa_key_now(priv, pkey); - mutex_lock(&priv->lock); - + lbs_schedule_wpa_key_work(priv); } out: |