diff options
author | Samuel Ortiz <samuel.ortiz@intel.com> | 2009-06-15 15:59:52 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-07-10 14:57:51 -0400 |
commit | 13e0fe70960e95cdea89b71aa3d046ec71efac8c (patch) | |
tree | 3cb98cc48285bac0b368f5ff2f3a97bad15cefc4 /drivers | |
parent | a70742f167424bab794ca74b9e99b598b358bb7d (diff) |
iwmc3200wifi: cfg80211 key hooks implemetation
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/cfg80211.c | 172 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/commands.c | 72 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/commands.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/iwm.h | 14 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/main.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/wext.c | 286 |
6 files changed, 219 insertions, 332 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index bc89b1ef0cad..739bd9b0ddea 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/netdevice.h> | 25 | #include <linux/netdevice.h> |
26 | #include <linux/etherdevice.h> | ||
26 | #include <linux/wireless.h> | 27 | #include <linux/wireless.h> |
27 | #include <linux/ieee80211.h> | 28 | #include <linux/ieee80211.h> |
28 | #include <net/cfg80211.h> | 29 | #include <net/cfg80211.h> |
@@ -130,6 +131,173 @@ static struct ieee80211_supported_band iwm_band_5ghz = { | |||
130 | .n_bitrates = iwm_a_rates_size, | 131 | .n_bitrates = iwm_a_rates_size, |
131 | }; | 132 | }; |
132 | 133 | ||
134 | static int iwm_key_init(struct iwm_key *key, u8 key_index, | ||
135 | const u8 *mac_addr, struct key_params *params) | ||
136 | { | ||
137 | key->hdr.key_idx = key_index; | ||
138 | if (!mac_addr || is_broadcast_ether_addr(mac_addr)) { | ||
139 | key->hdr.multicast = 1; | ||
140 | memset(key->hdr.mac, 0xff, ETH_ALEN); | ||
141 | } else { | ||
142 | key->hdr.multicast = 0; | ||
143 | memcpy(key->hdr.mac, mac_addr, ETH_ALEN); | ||
144 | } | ||
145 | |||
146 | if (params) { | ||
147 | if (params->key_len > WLAN_MAX_KEY_LEN || | ||
148 | params->seq_len > IW_ENCODE_SEQ_MAX_SIZE) | ||
149 | return -EINVAL; | ||
150 | |||
151 | key->cipher = params->cipher; | ||
152 | key->key_len = params->key_len; | ||
153 | key->seq_len = params->seq_len; | ||
154 | memcpy(key->key, params->key, key->key_len); | ||
155 | memcpy(key->seq, params->seq, key->seq_len); | ||
156 | } | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static int iwm_reset_profile(struct iwm_priv *iwm) | ||
162 | { | ||
163 | int ret; | ||
164 | |||
165 | if (!iwm->umac_profile_active) | ||
166 | return 0; | ||
167 | |||
168 | /* | ||
169 | * If there is a current active profile, but no | ||
170 | * default key, it's not worth trying to associate again. | ||
171 | */ | ||
172 | if (iwm->default_key < 0) | ||
173 | return 0; | ||
174 | |||
175 | /* | ||
176 | * Here we have an active profile, but a key setting changed. | ||
177 | * We thus have to invalidate the current profile, and push the | ||
178 | * new one. Keys will be pushed when association takes place. | ||
179 | */ | ||
180 | ret = iwm_invalidate_mlme_profile(iwm); | ||
181 | if (ret < 0) { | ||
182 | IWM_ERR(iwm, "Couldn't invalidate profile\n"); | ||
183 | return ret; | ||
184 | } | ||
185 | |||
186 | return iwm_send_mlme_profile(iwm); | ||
187 | } | ||
188 | |||
189 | static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | ||
190 | u8 key_index, const u8 *mac_addr, | ||
191 | struct key_params *params) | ||
192 | { | ||
193 | struct iwm_priv *iwm = ndev_to_iwm(ndev); | ||
194 | struct iwm_key *key = &iwm->keys[key_index]; | ||
195 | int ret; | ||
196 | |||
197 | IWM_DBG_WEXT(iwm, DBG, "Adding key for %pM\n", mac_addr); | ||
198 | |||
199 | memset(key, 0, sizeof(struct iwm_key)); | ||
200 | ret = iwm_key_init(key, key_index, mac_addr, params); | ||
201 | if (ret < 0) { | ||
202 | IWM_ERR(iwm, "Invalid key_params\n"); | ||
203 | return ret; | ||
204 | } | ||
205 | |||
206 | /* | ||
207 | * The WEP keys can be set before or after setting the essid. | ||
208 | * We need to handle both cases by simply pushing the keys after | ||
209 | * we send the profile. | ||
210 | * If the profile is not set yet (i.e. we're pushing keys before | ||
211 | * the essid), we set the cipher appropriately. | ||
212 | * If the profile is set, we havent associated yet because our | ||
213 | * cipher was incorrectly set. So we invalidate and send the | ||
214 | * profile again. | ||
215 | */ | ||
216 | if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || | ||
217 | key->cipher == WLAN_CIPHER_SUITE_WEP104) { | ||
218 | u8 *ucast_cipher = &iwm->umac_profile->sec.ucast_cipher; | ||
219 | u8 *mcast_cipher = &iwm->umac_profile->sec.mcast_cipher; | ||
220 | |||
221 | IWM_DBG_WEXT(iwm, DBG, "WEP key\n"); | ||
222 | |||
223 | if (key->cipher == WLAN_CIPHER_SUITE_WEP40) | ||
224 | *ucast_cipher = *mcast_cipher = UMAC_CIPHER_TYPE_WEP_40; | ||
225 | if (key->cipher == WLAN_CIPHER_SUITE_WEP104) | ||
226 | *ucast_cipher = *mcast_cipher = | ||
227 | UMAC_CIPHER_TYPE_WEP_104; | ||
228 | |||
229 | return iwm_reset_profile(iwm); | ||
230 | } | ||
231 | |||
232 | return iwm_set_key(iwm, 0, key); | ||
233 | } | ||
234 | |||
235 | static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, | ||
236 | u8 key_index, const u8 *mac_addr, void *cookie, | ||
237 | void (*callback)(void *cookie, | ||
238 | struct key_params*)) | ||
239 | { | ||
240 | struct iwm_priv *iwm = ndev_to_iwm(ndev); | ||
241 | struct iwm_key *key = &iwm->keys[key_index]; | ||
242 | struct key_params params; | ||
243 | |||
244 | IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index); | ||
245 | |||
246 | memset(¶ms, 0, sizeof(params)); | ||
247 | |||
248 | params.cipher = key->cipher; | ||
249 | params.key_len = key->key_len; | ||
250 | params.seq_len = key->seq_len; | ||
251 | params.seq = key->seq; | ||
252 | params.key = key->key; | ||
253 | |||
254 | callback(cookie, ¶ms); | ||
255 | |||
256 | return key->key_len ? 0 : -ENOENT; | ||
257 | } | ||
258 | |||
259 | |||
260 | static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, | ||
261 | u8 key_index, const u8 *mac_addr) | ||
262 | { | ||
263 | struct iwm_priv *iwm = ndev_to_iwm(ndev); | ||
264 | struct iwm_key *key = &iwm->keys[key_index]; | ||
265 | |||
266 | if (!iwm->keys[key_index].key_len) { | ||
267 | IWM_DBG_WEXT(iwm, DBG, "Key %d not used\n", key_index); | ||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | if (key_index == iwm->default_key) | ||
272 | iwm->default_key = -1; | ||
273 | |||
274 | return iwm_set_key(iwm, 1, key); | ||
275 | } | ||
276 | |||
277 | static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, | ||
278 | struct net_device *ndev, | ||
279 | u8 key_index) | ||
280 | { | ||
281 | struct iwm_priv *iwm = ndev_to_iwm(ndev); | ||
282 | int ret; | ||
283 | |||
284 | IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index); | ||
285 | |||
286 | if (!iwm->keys[key_index].key_len) { | ||
287 | IWM_ERR(iwm, "Key %d not used\n", key_index); | ||
288 | return -EINVAL; | ||
289 | } | ||
290 | |||
291 | ret = iwm_set_tx_key(iwm, key_index); | ||
292 | if (ret < 0) | ||
293 | return ret; | ||
294 | |||
295 | iwm->default_key = key_index; | ||
296 | |||
297 | return iwm_reset_profile(iwm); | ||
298 | } | ||
299 | |||
300 | |||
133 | int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) | 301 | int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) |
134 | { | 302 | { |
135 | struct wiphy *wiphy = iwm_to_wiphy(iwm); | 303 | struct wiphy *wiphy = iwm_to_wiphy(iwm); |
@@ -326,6 +494,10 @@ static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) | |||
326 | 494 | ||
327 | static struct cfg80211_ops iwm_cfg80211_ops = { | 495 | static struct cfg80211_ops iwm_cfg80211_ops = { |
328 | .change_virtual_intf = iwm_cfg80211_change_iface, | 496 | .change_virtual_intf = iwm_cfg80211_change_iface, |
497 | .add_key = iwm_cfg80211_add_key, | ||
498 | .get_key = iwm_cfg80211_get_key, | ||
499 | .del_key = iwm_cfg80211_del_key, | ||
500 | .set_default_key = iwm_cfg80211_set_default_key, | ||
329 | .scan = iwm_cfg80211_scan, | 501 | .scan = iwm_cfg80211_scan, |
330 | .set_wiphy_params = iwm_cfg80211_set_wiphy_params, | 502 | .set_wiphy_params = iwm_cfg80211_set_wiphy_params, |
331 | .join_ibss = iwm_cfg80211_join_ibss, | 503 | .join_ibss = iwm_cfg80211_join_ibss, |
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 337a884f52df..145f6f5ae747 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c | |||
@@ -524,9 +524,6 @@ int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx) | |||
524 | { | 524 | { |
525 | struct iwm_umac_tx_key_id tx_key_id; | 525 | struct iwm_umac_tx_key_id tx_key_id; |
526 | 526 | ||
527 | if (!iwm->default_key || !iwm->default_key->in_use) | ||
528 | return -EINVAL; | ||
529 | |||
530 | tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID; | 527 | tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID; |
531 | tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) - | 528 | tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) - |
532 | sizeof(struct iwm_umac_wifi_if)); | 529 | sizeof(struct iwm_umac_wifi_if)); |
@@ -569,10 +566,9 @@ static int iwm_check_profile(struct iwm_priv *iwm) | |||
569 | return 0; | 566 | return 0; |
570 | } | 567 | } |
571 | 568 | ||
572 | int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, | 569 | int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) |
573 | struct iwm_key *key) | ||
574 | { | 570 | { |
575 | int ret; | 571 | int ret = 0; |
576 | u8 cmd[64], *sta_addr, *key_data, key_len; | 572 | u8 cmd[64], *sta_addr, *key_data, key_len; |
577 | s8 key_idx; | 573 | s8 key_idx; |
578 | u16 cmd_size = 0; | 574 | u16 cmd_size = 0; |
@@ -582,9 +578,6 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, | |||
582 | struct iwm_umac_key_tkip *tkip = (struct iwm_umac_key_tkip *)cmd; | 578 | struct iwm_umac_key_tkip *tkip = (struct iwm_umac_key_tkip *)cmd; |
583 | struct iwm_umac_key_ccmp *ccmp = (struct iwm_umac_key_ccmp *)cmd; | 579 | struct iwm_umac_key_ccmp *ccmp = (struct iwm_umac_key_ccmp *)cmd; |
584 | 580 | ||
585 | if (set_tx_key) | ||
586 | iwm->default_key = key; | ||
587 | |||
588 | /* | 581 | /* |
589 | * We check if our current profile is valid. | 582 | * We check if our current profile is valid. |
590 | * If not, we dont push the key, we just cache them, | 583 | * 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, | |||
603 | key_idx = key->hdr.key_idx; | 596 | key_idx = key->hdr.key_idx; |
604 | 597 | ||
605 | if (!remove) { | 598 | if (!remove) { |
606 | IWM_DBG_WEXT(iwm, DBG, "key_idx:%d set tx key:%d\n", | 599 | IWM_DBG_WEXT(iwm, DBG, "key_idx:%d\n", key_idx); |
607 | key_idx, set_tx_key); | ||
608 | IWM_DBG_WEXT(iwm, DBG, "key_len:%d\n", key_len); | 600 | IWM_DBG_WEXT(iwm, DBG, "key_len:%d\n", key_len); |
609 | IWM_DBG_WEXT(iwm, DBG, "MAC:%pM, idx:%d, multicast:%d\n", | 601 | IWM_DBG_WEXT(iwm, DBG, "MAC:%pM, idx:%d, multicast:%d\n", |
610 | key_hdr->mac, key_hdr->key_idx, key_hdr->multicast); | 602 | 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, | |||
616 | iwm->umac_profile->sec.auth_type, | 608 | iwm->umac_profile->sec.auth_type, |
617 | iwm->umac_profile->sec.flags); | 609 | iwm->umac_profile->sec.flags); |
618 | 610 | ||
619 | switch (key->alg) { | 611 | switch (key->cipher) { |
620 | case UMAC_CIPHER_TYPE_WEP_40: | 612 | case WLAN_CIPHER_SUITE_WEP40: |
621 | wep40->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP40_KEY; | 613 | wep40->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP40_KEY; |
622 | wep40->hdr.buf_size = | 614 | wep40->hdr.buf_size = |
623 | cpu_to_le16(sizeof(struct iwm_umac_key_wep40) - | 615 | 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, | |||
631 | cmd_size = sizeof(struct iwm_umac_key_wep40); | 623 | cmd_size = sizeof(struct iwm_umac_key_wep40); |
632 | break; | 624 | break; |
633 | 625 | ||
634 | case UMAC_CIPHER_TYPE_WEP_104: | 626 | case WLAN_CIPHER_SUITE_WEP104: |
635 | wep104->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP104_KEY; | 627 | wep104->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP104_KEY; |
636 | wep104->hdr.buf_size = | 628 | wep104->hdr.buf_size = |
637 | cpu_to_le16(sizeof(struct iwm_umac_key_wep104) - | 629 | 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, | |||
645 | cmd_size = sizeof(struct iwm_umac_key_wep104); | 637 | cmd_size = sizeof(struct iwm_umac_key_wep104); |
646 | break; | 638 | break; |
647 | 639 | ||
648 | case UMAC_CIPHER_TYPE_CCMP: | 640 | case WLAN_CIPHER_SUITE_CCMP: |
649 | key_hdr->key_idx++; | 641 | key_hdr->key_idx++; |
650 | ccmp->hdr.oid = UMAC_WIFI_IF_CMD_ADD_CCMP_KEY; | 642 | ccmp->hdr.oid = UMAC_WIFI_IF_CMD_ADD_CCMP_KEY; |
651 | ccmp->hdr.buf_size = | 643 | ccmp->hdr.buf_size = |
@@ -657,13 +649,13 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, | |||
657 | 649 | ||
658 | memcpy(ccmp->key, key_data, key_len); | 650 | memcpy(ccmp->key, key_data, key_len); |
659 | 651 | ||
660 | if (key->flags & IW_ENCODE_EXT_RX_SEQ_VALID) | 652 | if (key->seq_len) |
661 | memcpy(ccmp->iv_count, key->rx_seq, 6); | 653 | memcpy(ccmp->iv_count, key->seq, key->seq_len); |
662 | 654 | ||
663 | cmd_size = sizeof(struct iwm_umac_key_ccmp); | 655 | cmd_size = sizeof(struct iwm_umac_key_ccmp); |
664 | break; | 656 | break; |
665 | 657 | ||
666 | case UMAC_CIPHER_TYPE_TKIP: | 658 | case WLAN_CIPHER_SUITE_TKIP: |
667 | key_hdr->key_idx++; | 659 | key_hdr->key_idx++; |
668 | tkip->hdr.oid = UMAC_WIFI_IF_CMD_ADD_TKIP_KEY; | 660 | tkip->hdr.oid = UMAC_WIFI_IF_CMD_ADD_TKIP_KEY; |
669 | tkip->hdr.buf_size = | 661 | tkip->hdr.buf_size = |
@@ -680,8 +672,8 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, | |||
680 | key_data + IWM_TKIP_KEY_SIZE + IWM_TKIP_MIC_SIZE, | 672 | key_data + IWM_TKIP_KEY_SIZE + IWM_TKIP_MIC_SIZE, |
681 | IWM_TKIP_MIC_SIZE); | 673 | IWM_TKIP_MIC_SIZE); |
682 | 674 | ||
683 | if (key->flags & IW_ENCODE_EXT_RX_SEQ_VALID) | 675 | if (key->seq_len) |
684 | memcpy(ccmp->iv_count, key->rx_seq, 6); | 676 | memcpy(ccmp->iv_count, key->seq, key->seq_len); |
685 | 677 | ||
686 | cmd_size = sizeof(struct iwm_umac_key_tkip); | 678 | cmd_size = sizeof(struct iwm_umac_key_tkip); |
687 | break; | 679 | break; |
@@ -690,8 +682,8 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, | |||
690 | return -ENOTSUPP; | 682 | return -ENOTSUPP; |
691 | } | 683 | } |
692 | 684 | ||
693 | if ((key->alg == UMAC_CIPHER_TYPE_CCMP) || | 685 | if ((key->cipher == WLAN_CIPHER_SUITE_TKIP) || |
694 | (key->alg == UMAC_CIPHER_TYPE_TKIP)) | 686 | (key->cipher == WLAN_CIPHER_SUITE_CCMP)) |
695 | /* | 687 | /* |
696 | * UGLY_UGLY_UGLY | 688 | * UGLY_UGLY_UGLY |
697 | * Copied HACK from the MWG driver. | 689 | * Copied HACK from the MWG driver. |
@@ -702,23 +694,11 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, | |||
702 | schedule_timeout_interruptible(usecs_to_jiffies(300)); | 694 | schedule_timeout_interruptible(usecs_to_jiffies(300)); |
703 | 695 | ||
704 | ret = iwm_send_wifi_if_cmd(iwm, cmd, cmd_size, 1); | 696 | ret = iwm_send_wifi_if_cmd(iwm, cmd, cmd_size, 1); |
705 | if (ret < 0) | ||
706 | goto err; | ||
707 | |||
708 | /* | ||
709 | * We need a default key only if it is set and | ||
710 | * if we're doing WEP. | ||
711 | */ | ||
712 | if (iwm->default_key == key && | ||
713 | ((key->alg == UMAC_CIPHER_TYPE_WEP_40) || | ||
714 | (key->alg == UMAC_CIPHER_TYPE_WEP_104))) { | ||
715 | ret = iwm_set_tx_key(iwm, key_idx); | ||
716 | if (ret < 0) | ||
717 | goto err; | ||
718 | } | ||
719 | } else { | 697 | } else { |
720 | struct iwm_umac_key_remove key_remove; | 698 | struct iwm_umac_key_remove key_remove; |
721 | 699 | ||
700 | IWM_DBG_WEXT(iwm, ERR, "Removing key_idx:%d\n", key_idx); | ||
701 | |||
722 | key_remove.hdr.oid = UMAC_WIFI_IF_CMD_REMOVE_KEY; | 702 | key_remove.hdr.oid = UMAC_WIFI_IF_CMD_REMOVE_KEY; |
723 | key_remove.hdr.buf_size = | 703 | key_remove.hdr.buf_size = |
724 | cpu_to_le16(sizeof(struct iwm_umac_key_remove) - | 704 | 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, | |||
732 | if (ret < 0) | 712 | if (ret < 0) |
733 | return ret; | 713 | return ret; |
734 | 714 | ||
735 | iwm->keys[key_idx].in_use = 0; | 715 | iwm->keys[key_idx].key_len = 0; |
736 | } | 716 | } |
737 | 717 | ||
738 | return 0; | ||
739 | |||
740 | err: | ||
741 | kfree(key); | ||
742 | return ret; | 718 | return ret; |
743 | } | 719 | } |
744 | 720 | ||
@@ -761,22 +737,24 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm) | |||
761 | } | 737 | } |
762 | 738 | ||
763 | for (i = 0; i < IWM_NUM_KEYS; i++) | 739 | for (i = 0; i < IWM_NUM_KEYS; i++) |
764 | if (iwm->keys[i].in_use) { | 740 | if (iwm->keys[i].key_len) { |
765 | int default_key = 0; | ||
766 | struct iwm_key *key = &iwm->keys[i]; | 741 | struct iwm_key *key = &iwm->keys[i]; |
767 | 742 | ||
768 | if (key == iwm->default_key) | ||
769 | default_key = 1; | ||
770 | |||
771 | /* Wait for the profile before sending the keys */ | 743 | /* Wait for the profile before sending the keys */ |
772 | wait_event_interruptible_timeout(iwm->mlme_queue, | 744 | wait_event_interruptible_timeout(iwm->mlme_queue, |
773 | (test_bit(IWM_STATUS_ASSOCIATING, &iwm->status) || | 745 | (test_bit(IWM_STATUS_ASSOCIATING, &iwm->status) || |
774 | test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)), | 746 | test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)), |
775 | 3 * HZ); | 747 | 3 * HZ); |
776 | 748 | ||
777 | ret = iwm_set_key(iwm, 0, default_key, key); | 749 | ret = iwm_set_key(iwm, 0, key); |
778 | if (ret < 0) | 750 | if (ret < 0) |
779 | return ret; | 751 | return ret; |
752 | |||
753 | if (iwm->default_key == i) { | ||
754 | ret = iwm_set_tx_key(iwm, i); | ||
755 | if (ret < 0) | ||
756 | return ret; | ||
757 | } | ||
780 | } | 758 | } |
781 | 759 | ||
782 | return 0; | 760 | return 0; |
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.h b/drivers/net/wireless/iwmc3200wifi/commands.h index 36b13a130595..3510df8ff391 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.h +++ b/drivers/net/wireless/iwmc3200wifi/commands.h | |||
@@ -406,8 +406,7 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm); | |||
406 | int iwm_invalidate_mlme_profile(struct iwm_priv *iwm); | 406 | int iwm_invalidate_mlme_profile(struct iwm_priv *iwm); |
407 | int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id); | 407 | int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id); |
408 | int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx); | 408 | int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx); |
409 | int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, | 409 | int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key); |
410 | struct iwm_key *key); | ||
411 | int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags); | 410 | int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags); |
412 | int iwm_send_umac_channel_list(struct iwm_priv *iwm); | 411 | int iwm_send_umac_channel_list(struct iwm_priv *iwm); |
413 | int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids, | 412 | int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids, |
diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index d8d4ae2d91b0..90b05d999635 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h | |||
@@ -162,13 +162,11 @@ struct iwm_umac_key_hdr { | |||
162 | 162 | ||
163 | struct iwm_key { | 163 | struct iwm_key { |
164 | struct iwm_umac_key_hdr hdr; | 164 | struct iwm_umac_key_hdr hdr; |
165 | u8 in_use; | 165 | u32 cipher; |
166 | u8 alg; | 166 | u8 key[WLAN_MAX_KEY_LEN]; |
167 | u32 flags; | 167 | u8 seq[IW_ENCODE_SEQ_MAX_SIZE]; |
168 | u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; | 168 | int key_len; |
169 | u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; | 169 | int seq_len; |
170 | u8 key_len; | ||
171 | u8 key[32]; | ||
172 | }; | 170 | }; |
173 | 171 | ||
174 | #define IWM_RX_ID_HASH 0xff | 172 | #define IWM_RX_ID_HASH 0xff |
@@ -276,7 +274,7 @@ struct iwm_priv { | |||
276 | struct iwm_tx_queue txq[IWM_TX_QUEUES]; | 274 | struct iwm_tx_queue txq[IWM_TX_QUEUES]; |
277 | 275 | ||
278 | struct iwm_key keys[IWM_NUM_KEYS]; | 276 | struct iwm_key keys[IWM_NUM_KEYS]; |
279 | struct iwm_key *default_key; | 277 | s8 default_key; |
280 | 278 | ||
281 | DECLARE_BITMAP(wifi_ntfy, WIFI_IF_NTFY_MAX); | 279 | DECLARE_BITMAP(wifi_ntfy, WIFI_IF_NTFY_MAX); |
282 | wait_queue_head_t wifi_ntfy_queue; | 280 | wait_queue_head_t wifi_ntfy_queue; |
diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index 844872213a12..7f56c06a53db 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c | |||
@@ -230,7 +230,7 @@ int iwm_priv_init(struct iwm_priv *iwm) | |||
230 | for (i = 0; i < IWM_NUM_KEYS; i++) | 230 | for (i = 0; i < IWM_NUM_KEYS; i++) |
231 | memset(&iwm->keys[i], 0, sizeof(struct iwm_key)); | 231 | memset(&iwm->keys[i], 0, sizeof(struct iwm_key)); |
232 | 232 | ||
233 | iwm->default_key = NULL; | 233 | iwm->default_key = -1; |
234 | 234 | ||
235 | init_timer(&iwm->watchdog); | 235 | init_timer(&iwm->watchdog); |
236 | iwm->watchdog.function = iwm_watchdog; | 236 | iwm->watchdog.function = iwm_watchdog; |
@@ -709,7 +709,7 @@ int __iwm_down(struct iwm_priv *iwm) | |||
709 | iwm->umac_profile = NULL; | 709 | iwm->umac_profile = NULL; |
710 | iwm_bss_list_clean(iwm); | 710 | iwm_bss_list_clean(iwm); |
711 | 711 | ||
712 | iwm->default_key = NULL; | 712 | iwm->default_key = -1; |
713 | iwm->core_enabled = 0; | 713 | iwm->core_enabled = 0; |
714 | 714 | ||
715 | ret = iwm_bus_disable(iwm); | 715 | ret = iwm_bus_disable(iwm); |
diff --git a/drivers/net/wireless/iwmc3200wifi/wext.c b/drivers/net/wireless/iwmc3200wifi/wext.c index 889194931b4e..3062f37bbe95 100644 --- a/drivers/net/wireless/iwmc3200wifi/wext.c +++ b/drivers/net/wireless/iwmc3200wifi/wext.c | |||
@@ -84,6 +84,8 @@ static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info, | |||
84 | struct iwm_priv *iwm = ndev_to_iwm(dev); | 84 | struct iwm_priv *iwm = ndev_to_iwm(dev); |
85 | int ret; | 85 | int ret; |
86 | 86 | ||
87 | IWM_DBG_WEXT(iwm, DBG, "Set BSSID: %pM\n", ap_addr->sa_data); | ||
88 | |||
87 | if (iwm->conf.mode == UMAC_MODE_IBSS) | 89 | if (iwm->conf.mode == UMAC_MODE_IBSS) |
88 | return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); | 90 | return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); |
89 | 91 | ||
@@ -116,8 +118,7 @@ static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info, | |||
116 | */ | 118 | */ |
117 | if (is_zero_ether_addr(ap_addr->sa_data)) { | 119 | if (is_zero_ether_addr(ap_addr->sa_data)) { |
118 | for (i = 0; i < IWM_NUM_KEYS; i++) | 120 | for (i = 0; i < IWM_NUM_KEYS; i++) |
119 | iwm->keys[i].in_use = 0; | 121 | iwm->keys[i].key_len = 0; |
120 | |||
121 | } | 122 | } |
122 | 123 | ||
123 | ret = iwm_invalidate_mlme_profile(iwm); | 124 | ret = iwm_invalidate_mlme_profile(iwm); |
@@ -163,6 +164,8 @@ static int iwm_wext_siwessid(struct net_device *dev, | |||
163 | size_t len = data->length; | 164 | size_t len = data->length; |
164 | int ret; | 165 | int ret; |
165 | 166 | ||
167 | IWM_DBG_WEXT(iwm, DBG, "Set ESSID: >%s<\n", ssid); | ||
168 | |||
166 | if (iwm->conf.mode == UMAC_MODE_IBSS) | 169 | if (iwm->conf.mode == UMAC_MODE_IBSS) |
167 | return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); | 170 | return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); |
168 | 171 | ||
@@ -212,27 +215,6 @@ static int iwm_wext_giwessid(struct net_device *dev, | |||
212 | return 0; | 215 | return 0; |
213 | } | 216 | } |
214 | 217 | ||
215 | static struct iwm_key * | ||
216 | iwm_key_init(struct iwm_priv *iwm, u8 key_idx, bool in_use, | ||
217 | struct iw_encode_ext *ext, u8 alg) | ||
218 | { | ||
219 | struct iwm_key *key = &iwm->keys[key_idx]; | ||
220 | |||
221 | memset(key, 0, sizeof(struct iwm_key)); | ||
222 | memcpy(key->hdr.mac, ext->addr.sa_data, ETH_ALEN); | ||
223 | key->hdr.key_idx = key_idx; | ||
224 | if (is_broadcast_ether_addr(ext->addr.sa_data)) | ||
225 | key->hdr.multicast = 1; | ||
226 | |||
227 | key->in_use = in_use; | ||
228 | key->flags = ext->ext_flags; | ||
229 | key->alg = alg; | ||
230 | key->key_len = ext->key_len; | ||
231 | memcpy(key->key, ext->key, ext->key_len); | ||
232 | |||
233 | return key; | ||
234 | } | ||
235 | |||
236 | static int iwm_wext_giwrate(struct net_device *dev, | 218 | static int iwm_wext_giwrate(struct net_device *dev, |
237 | struct iw_request_info *info, | 219 | struct iw_request_info *info, |
238 | struct iw_param *rate, char *extra) | 220 | struct iw_param *rate, char *extra) |
@@ -244,184 +226,6 @@ static int iwm_wext_giwrate(struct net_device *dev, | |||
244 | return 0; | 226 | return 0; |
245 | } | 227 | } |
246 | 228 | ||
247 | static int iwm_wext_siwencode(struct net_device *dev, | ||
248 | struct iw_request_info *info, | ||
249 | struct iw_point *erq, char *key_buf) | ||
250 | { | ||
251 | struct iwm_priv *iwm = ndev_to_iwm(dev); | ||
252 | struct iwm_key *uninitialized_var(key); | ||
253 | int idx, i, uninitialized_var(alg), remove = 0, ret; | ||
254 | |||
255 | IWM_DBG_WEXT(iwm, DBG, "key len: %d\n", erq->length); | ||
256 | IWM_DBG_WEXT(iwm, DBG, "flags: 0x%x\n", erq->flags); | ||
257 | |||
258 | if (!iwm->umac_profile) { | ||
259 | IWM_ERR(iwm, "UMAC profile not allocated yet\n"); | ||
260 | return -ENODEV; | ||
261 | } | ||
262 | |||
263 | if (erq->length == WLAN_KEY_LEN_WEP40) { | ||
264 | alg = UMAC_CIPHER_TYPE_WEP_40; | ||
265 | iwm->umac_profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_WEP_40; | ||
266 | iwm->umac_profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_WEP_40; | ||
267 | } else if (erq->length == WLAN_KEY_LEN_WEP104) { | ||
268 | alg = UMAC_CIPHER_TYPE_WEP_104; | ||
269 | iwm->umac_profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_WEP_104; | ||
270 | iwm->umac_profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_WEP_104; | ||
271 | } | ||
272 | |||
273 | if (erq->flags & IW_ENCODE_RESTRICTED) | ||
274 | iwm->umac_profile->sec.auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; | ||
275 | else | ||
276 | iwm->umac_profile->sec.auth_type = UMAC_AUTH_TYPE_OPEN; | ||
277 | |||
278 | idx = erq->flags & IW_ENCODE_INDEX; | ||
279 | if (idx == 0) { | ||
280 | if (iwm->default_key) | ||
281 | for (i = 0; i < IWM_NUM_KEYS; i++) { | ||
282 | if (iwm->default_key == &iwm->keys[i]) { | ||
283 | idx = i; | ||
284 | break; | ||
285 | } | ||
286 | } | ||
287 | else | ||
288 | iwm->default_key = &iwm->keys[idx]; | ||
289 | } else if (idx < 1 || idx > 4) { | ||
290 | return -EINVAL; | ||
291 | } else | ||
292 | idx--; | ||
293 | |||
294 | if (erq->flags & IW_ENCODE_DISABLED) | ||
295 | remove = 1; | ||
296 | else if (erq->length == 0) { | ||
297 | if (!iwm->keys[idx].in_use) | ||
298 | return -EINVAL; | ||
299 | iwm->default_key = &iwm->keys[idx]; | ||
300 | } | ||
301 | |||
302 | if (erq->length) { | ||
303 | key = &iwm->keys[idx]; | ||
304 | memset(key, 0, sizeof(struct iwm_key)); | ||
305 | memset(key->hdr.mac, 0xff, ETH_ALEN); | ||
306 | key->hdr.key_idx = idx; | ||
307 | key->hdr.multicast = 1; | ||
308 | key->in_use = !remove; | ||
309 | key->alg = alg; | ||
310 | key->key_len = erq->length; | ||
311 | memcpy(key->key, key_buf, erq->length); | ||
312 | |||
313 | IWM_DBG_WEXT(iwm, DBG, "Setting key %d, default: %d\n", | ||
314 | idx, !!iwm->default_key); | ||
315 | } | ||
316 | |||
317 | if (remove) { | ||
318 | if ((erq->flags & IW_ENCODE_NOKEY) || (erq->length == 0)) { | ||
319 | int j; | ||
320 | for (j = 0; j < IWM_NUM_KEYS; j++) | ||
321 | if (iwm->keys[j].in_use) { | ||
322 | struct iwm_key *k = &iwm->keys[j]; | ||
323 | |||
324 | k->in_use = 0; | ||
325 | ret = iwm_set_key(iwm, remove, 0, k); | ||
326 | if (ret < 0) | ||
327 | return ret; | ||
328 | } | ||
329 | |||
330 | iwm->umac_profile->sec.ucast_cipher = | ||
331 | UMAC_CIPHER_TYPE_NONE; | ||
332 | iwm->umac_profile->sec.mcast_cipher = | ||
333 | UMAC_CIPHER_TYPE_NONE; | ||
334 | iwm->umac_profile->sec.auth_type = | ||
335 | UMAC_AUTH_TYPE_OPEN; | ||
336 | |||
337 | return 0; | ||
338 | } else { | ||
339 | key->in_use = 0; | ||
340 | return iwm_set_key(iwm, remove, 0, key); | ||
341 | } | ||
342 | } | ||
343 | |||
344 | /* | ||
345 | * If we havent set a profile yet, we cant set keys. | ||
346 | * Keys will be pushed after we're associated. | ||
347 | */ | ||
348 | if (!iwm->umac_profile_active) | ||
349 | return 0; | ||
350 | |||
351 | /* | ||
352 | * If there is a current active profile, but no | ||
353 | * default key, it's not worth trying to associate again. | ||
354 | */ | ||
355 | if (!iwm->default_key) | ||
356 | return 0; | ||
357 | |||
358 | /* | ||
359 | * Here we have an active profile, but a key setting changed. | ||
360 | * We thus have to invalidate the current profile, and push the | ||
361 | * new one. Keys will be pushed when association takes place. | ||
362 | */ | ||
363 | ret = iwm_invalidate_mlme_profile(iwm); | ||
364 | if (ret < 0) { | ||
365 | IWM_ERR(iwm, "Couldn't invalidate profile\n"); | ||
366 | return ret; | ||
367 | } | ||
368 | |||
369 | return iwm_send_mlme_profile(iwm); | ||
370 | } | ||
371 | |||
372 | static int iwm_wext_giwencode(struct net_device *dev, | ||
373 | struct iw_request_info *info, | ||
374 | struct iw_point *erq, char *key) | ||
375 | { | ||
376 | struct iwm_priv *iwm = ndev_to_iwm(dev); | ||
377 | int idx, i; | ||
378 | |||
379 | idx = erq->flags & IW_ENCODE_INDEX; | ||
380 | if (idx < 1 || idx > 4) { | ||
381 | idx = -1; | ||
382 | if (!iwm->default_key) { | ||
383 | erq->length = 0; | ||
384 | erq->flags |= IW_ENCODE_NOKEY; | ||
385 | return 0; | ||
386 | } else | ||
387 | for (i = 0; i < IWM_NUM_KEYS; i++) { | ||
388 | if (iwm->default_key == &iwm->keys[i]) { | ||
389 | idx = i; | ||
390 | break; | ||
391 | } | ||
392 | } | ||
393 | if (idx < 0) | ||
394 | return -EINVAL; | ||
395 | } else | ||
396 | idx--; | ||
397 | |||
398 | erq->flags = idx + 1; | ||
399 | |||
400 | if (!iwm->keys[idx].in_use) { | ||
401 | erq->length = 0; | ||
402 | erq->flags |= IW_ENCODE_DISABLED; | ||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | memcpy(key, iwm->keys[idx].key, | ||
407 | min_t(int, erq->length, iwm->keys[idx].key_len)); | ||
408 | erq->length = iwm->keys[idx].key_len; | ||
409 | erq->flags |= IW_ENCODE_ENABLED; | ||
410 | |||
411 | if (iwm->umac_profile->mode == UMAC_MODE_BSS) { | ||
412 | switch (iwm->umac_profile->sec.auth_type) { | ||
413 | case UMAC_AUTH_TYPE_OPEN: | ||
414 | erq->flags |= IW_ENCODE_OPEN; | ||
415 | break; | ||
416 | default: | ||
417 | erq->flags |= IW_ENCODE_RESTRICTED; | ||
418 | break; | ||
419 | } | ||
420 | } | ||
421 | |||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | static int iwm_set_wpa_version(struct iwm_priv *iwm, u8 wpa_version) | 229 | static int iwm_set_wpa_version(struct iwm_priv *iwm, u8 wpa_version) |
426 | { | 230 | { |
427 | if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) | 231 | 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) | |||
481 | { | 285 | { |
482 | u8 *auth_type = &iwm->umac_profile->sec.auth_type; | 286 | u8 *auth_type = &iwm->umac_profile->sec.auth_type; |
483 | 287 | ||
288 | IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt); | ||
289 | |||
484 | if (key_mgt == IW_AUTH_KEY_MGMT_802_1X) | 290 | if (key_mgt == IW_AUTH_KEY_MGMT_802_1X) |
485 | *auth_type = UMAC_AUTH_TYPE_8021X; | 291 | *auth_type = UMAC_AUTH_TYPE_8021X; |
486 | else if (key_mgt == IW_AUTH_KEY_MGMT_PSK) { | 292 | 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) | |||
530 | { | 336 | { |
531 | u8 *auth_type = &iwm->umac_profile->sec.auth_type; | 337 | u8 *auth_type = &iwm->umac_profile->sec.auth_type; |
532 | 338 | ||
339 | IWM_DBG_WEXT(iwm, DBG, "auth_alg: 0x%x\n", auth_alg); | ||
340 | |||
533 | switch (auth_alg) { | 341 | switch (auth_alg) { |
534 | case IW_AUTH_ALG_OPEN_SYSTEM: | 342 | case IW_AUTH_ALG_OPEN_SYSTEM: |
535 | *auth_type = UMAC_AUTH_TYPE_OPEN; | 343 | *auth_type = UMAC_AUTH_TYPE_OPEN; |
@@ -541,6 +349,7 @@ static int iwm_set_auth_alg(struct iwm_priv *iwm, u8 auth_alg) | |||
541 | return -EINVAL; | 349 | return -EINVAL; |
542 | *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; | 350 | *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; |
543 | } else { | 351 | } else { |
352 | IWM_DBG_WEXT(iwm, DBG, "WEP shared key\n"); | ||
544 | *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; | 353 | *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; |
545 | } | 354 | } |
546 | break; | 355 | break; |
@@ -603,75 +412,6 @@ static int iwm_wext_giwauth(struct net_device *dev, | |||
603 | return 0; | 412 | return 0; |
604 | } | 413 | } |
605 | 414 | ||
606 | static int iwm_wext_siwencodeext(struct net_device *dev, | ||
607 | struct iw_request_info *info, | ||
608 | struct iw_point *erq, char *extra) | ||
609 | { | ||
610 | struct iwm_priv *iwm = ndev_to_iwm(dev); | ||
611 | struct iwm_key *key; | ||
612 | struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; | ||
613 | int uninitialized_var(alg), idx, i, remove = 0; | ||
614 | |||
615 | IWM_DBG_WEXT(iwm, DBG, "alg: 0x%x\n", ext->alg); | ||
616 | IWM_DBG_WEXT(iwm, DBG, "key len: %d\n", ext->key_len); | ||
617 | IWM_DBG_WEXT(iwm, DBG, "ext_flags: 0x%x\n", ext->ext_flags); | ||
618 | IWM_DBG_WEXT(iwm, DBG, "flags: 0x%x\n", erq->flags); | ||
619 | IWM_DBG_WEXT(iwm, DBG, "length: 0x%x\n", erq->length); | ||
620 | |||
621 | switch (ext->alg) { | ||
622 | case IW_ENCODE_ALG_NONE: | ||
623 | remove = 1; | ||
624 | break; | ||
625 | case IW_ENCODE_ALG_WEP: | ||
626 | if (ext->key_len == WLAN_KEY_LEN_WEP40) | ||
627 | alg = UMAC_CIPHER_TYPE_WEP_40; | ||
628 | else if (ext->key_len == WLAN_KEY_LEN_WEP104) | ||
629 | alg = UMAC_CIPHER_TYPE_WEP_104; | ||
630 | else { | ||
631 | IWM_ERR(iwm, "Invalid key length: %d\n", ext->key_len); | ||
632 | return -EINVAL; | ||
633 | } | ||
634 | |||
635 | break; | ||
636 | case IW_ENCODE_ALG_TKIP: | ||
637 | alg = UMAC_CIPHER_TYPE_TKIP; | ||
638 | break; | ||
639 | case IW_ENCODE_ALG_CCMP: | ||
640 | alg = UMAC_CIPHER_TYPE_CCMP; | ||
641 | break; | ||
642 | default: | ||
643 | return -EOPNOTSUPP; | ||
644 | } | ||
645 | |||
646 | idx = erq->flags & IW_ENCODE_INDEX; | ||
647 | |||
648 | if (idx == 0) { | ||
649 | if (iwm->default_key) | ||
650 | for (i = 0; i < IWM_NUM_KEYS; i++) { | ||
651 | if (iwm->default_key == &iwm->keys[i]) { | ||
652 | idx = i; | ||
653 | break; | ||
654 | } | ||
655 | } | ||
656 | } else if (idx < 1 || idx > 4) { | ||
657 | return -EINVAL; | ||
658 | } else | ||
659 | idx--; | ||
660 | |||
661 | if (erq->flags & IW_ENCODE_DISABLED) | ||
662 | remove = 1; | ||
663 | else if ((erq->length == 0) || | ||
664 | (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) { | ||
665 | iwm->default_key = &iwm->keys[idx]; | ||
666 | if (iwm->umac_profile_active && ext->alg == IW_ENCODE_ALG_WEP) | ||
667 | return iwm_set_tx_key(iwm, idx); | ||
668 | } | ||
669 | |||
670 | key = iwm_key_init(iwm, idx, !remove, ext, alg); | ||
671 | |||
672 | return iwm_set_key(iwm, remove, !iwm->default_key, key); | ||
673 | } | ||
674 | |||
675 | static const iw_handler iwm_handlers[] = | 415 | static const iw_handler iwm_handlers[] = |
676 | { | 416 | { |
677 | (iw_handler) NULL, /* SIOCSIWCOMMIT */ | 417 | (iw_handler) NULL, /* SIOCSIWCOMMIT */ |
@@ -716,8 +456,8 @@ static const iw_handler iwm_handlers[] = | |||
716 | (iw_handler) NULL, /* SIOCGIWTXPOW */ | 456 | (iw_handler) NULL, /* SIOCGIWTXPOW */ |
717 | (iw_handler) NULL, /* SIOCSIWRETRY */ | 457 | (iw_handler) NULL, /* SIOCSIWRETRY */ |
718 | (iw_handler) NULL, /* SIOCGIWRETRY */ | 458 | (iw_handler) NULL, /* SIOCGIWRETRY */ |
719 | (iw_handler) iwm_wext_siwencode, /* SIOCSIWENCODE */ | 459 | (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */ |
720 | (iw_handler) iwm_wext_giwencode, /* SIOCGIWENCODE */ | 460 | (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */ |
721 | (iw_handler) iwm_wext_siwpower, /* SIOCSIWPOWER */ | 461 | (iw_handler) iwm_wext_siwpower, /* SIOCSIWPOWER */ |
722 | (iw_handler) iwm_wext_giwpower, /* SIOCGIWPOWER */ | 462 | (iw_handler) iwm_wext_giwpower, /* SIOCGIWPOWER */ |
723 | (iw_handler) NULL, /* -- hole -- */ | 463 | (iw_handler) NULL, /* -- hole -- */ |
@@ -726,7 +466,7 @@ static const iw_handler iwm_handlers[] = | |||
726 | (iw_handler) NULL, /* SIOCGIWGENIE */ | 466 | (iw_handler) NULL, /* SIOCGIWGENIE */ |
727 | (iw_handler) iwm_wext_siwauth, /* SIOCSIWAUTH */ | 467 | (iw_handler) iwm_wext_siwauth, /* SIOCSIWAUTH */ |
728 | (iw_handler) iwm_wext_giwauth, /* SIOCGIWAUTH */ | 468 | (iw_handler) iwm_wext_giwauth, /* SIOCGIWAUTH */ |
729 | (iw_handler) iwm_wext_siwencodeext, /* SIOCSIWENCODEEXT */ | 469 | (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */ |
730 | (iw_handler) NULL, /* SIOCGIWENCODEEXT */ | 470 | (iw_handler) NULL, /* SIOCGIWENCODEEXT */ |
731 | (iw_handler) NULL, /* SIOCSIWPMKSA */ | 471 | (iw_handler) NULL, /* SIOCSIWPMKSA */ |
732 | (iw_handler) NULL, /* -- hole -- */ | 472 | (iw_handler) NULL, /* -- hole -- */ |