aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/nl80211.h5
-rw-r--r--include/net/cfg80211.h18
-rw-r--r--net/mac80211/ibss.c9
-rw-r--r--net/mac80211/ieee80211_i.h8
-rw-r--r--net/mac80211/mlme.c11
-rw-r--r--net/mac80211/util.c16
-rw-r--r--net/mac80211/wep.c6
-rw-r--r--net/mac80211/wep.h3
-rw-r--r--net/wireless/core.c11
-rw-r--r--net/wireless/core.h32
-rw-r--r--net/wireless/ibss.c79
-rw-r--r--net/wireless/mlme.c16
-rw-r--r--net/wireless/nl80211.c170
-rw-r--r--net/wireless/sme.c97
-rw-r--r--net/wireless/util.c41
-rw-r--r--net/wireless/wext-compat.c163
-rw-r--r--net/wireless/wext-sme.c30
17 files changed, 554 insertions, 161 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 48e0913c2209..b043b78dd2c3 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -569,6 +569,9 @@ enum nl80211_commands {
569 * 569 *
570 * @NL80211_ATTR_KEY: key information in a nested attribute with 570 * @NL80211_ATTR_KEY: key information in a nested attribute with
571 * %NL80211_KEY_* sub-attributes 571 * %NL80211_KEY_* sub-attributes
572 * @NL80211_ATTR_KEYS: array of keys for static WEP keys for connect()
573 * and join_ibss(), key information is in a nested attribute each
574 * with %NL80211_KEY_* sub-attributes
572 * 575 *
573 * @NL80211_ATTR_MAX: highest attribute number currently defined 576 * @NL80211_ATTR_MAX: highest attribute number currently defined
574 * @__NL80211_ATTR_AFTER_LAST: internal use 577 * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -696,6 +699,7 @@ enum nl80211_attrs {
696 NL80211_ATTR_PREV_BSSID, 699 NL80211_ATTR_PREV_BSSID,
697 700
698 NL80211_ATTR_KEY, 701 NL80211_ATTR_KEY,
702 NL80211_ATTR_KEYS,
699 703
700 /* add attributes here, update the policy in nl80211.c */ 704 /* add attributes here, update the policy in nl80211.c */
701 705
@@ -726,6 +730,7 @@ enum nl80211_attrs {
726#define NL80211_ATTR_WPA_VERSIONS NL80211_ATTR_WPA_VERSIONS 730#define NL80211_ATTR_WPA_VERSIONS NL80211_ATTR_WPA_VERSIONS
727#define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES 731#define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES
728#define NL80211_ATTR_KEY NL80211_ATTR_KEY 732#define NL80211_ATTR_KEY NL80211_ATTR_KEY
733#define NL80211_ATTR_KEYS NL80211_ATTR_KEYS
729 734
730#define NL80211_MAX_SUPP_RATES 32 735#define NL80211_MAX_SUPP_RATES 32
731#define NL80211_MAX_SUPP_REG_RULES 32 736#define NL80211_MAX_SUPP_REG_RULES 32
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 83c2c727d71e..65a5cbcb5d14 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -647,12 +647,17 @@ struct cfg80211_crypto_settings {
647 * @auth_type: Authentication type (algorithm) 647 * @auth_type: Authentication type (algorithm)
648 * @ie: Extra IEs to add to Authentication frame or %NULL 648 * @ie: Extra IEs to add to Authentication frame or %NULL
649 * @ie_len: Length of ie buffer in octets 649 * @ie_len: Length of ie buffer in octets
650 * @key_len: length of WEP key for shared key authentication
651 * @key_idx: index of WEP key for shared key authentication
652 * @key: WEP key for shared key authentication
650 */ 653 */
651struct cfg80211_auth_request { 654struct cfg80211_auth_request {
652 struct cfg80211_bss *bss; 655 struct cfg80211_bss *bss;
653 const u8 *ie; 656 const u8 *ie;
654 size_t ie_len; 657 size_t ie_len;
655 enum nl80211_auth_type auth_type; 658 enum nl80211_auth_type auth_type;
659 const u8 *key;
660 u8 key_len, key_idx;
656}; 661};
657 662
658/** 663/**
@@ -727,6 +732,8 @@ struct cfg80211_disassoc_request {
727 * @ie: information element(s) to include in the beacon 732 * @ie: information element(s) to include in the beacon
728 * @ie_len: length of that 733 * @ie_len: length of that
729 * @beacon_interval: beacon interval to use 734 * @beacon_interval: beacon interval to use
735 * @privacy: this is a protected network, keys will be configured
736 * after joining
730 */ 737 */
731struct cfg80211_ibss_params { 738struct cfg80211_ibss_params {
732 u8 *ssid; 739 u8 *ssid;
@@ -736,6 +743,7 @@ struct cfg80211_ibss_params {
736 u8 ssid_len, ie_len; 743 u8 ssid_len, ie_len;
737 u16 beacon_interval; 744 u16 beacon_interval;
738 bool channel_fixed; 745 bool channel_fixed;
746 bool privacy;
739}; 747};
740 748
741/** 749/**
@@ -755,6 +763,9 @@ struct cfg80211_ibss_params {
755 * @assoc_ie_len: Length of assoc_ie in octets 763 * @assoc_ie_len: Length of assoc_ie in octets
756 * @privacy: indicates whether privacy-enabled APs should be used 764 * @privacy: indicates whether privacy-enabled APs should be used
757 * @crypto: crypto settings 765 * @crypto: crypto settings
766 * @key_len: length of WEP key for shared key authentication
767 * @key_idx: index of WEP key for shared key authentication
768 * @key: WEP key for shared key authentication
758 */ 769 */
759struct cfg80211_connect_params { 770struct cfg80211_connect_params {
760 struct ieee80211_channel *channel; 771 struct ieee80211_channel *channel;
@@ -766,6 +777,8 @@ struct cfg80211_connect_params {
766 size_t ie_len; 777 size_t ie_len;
767 bool privacy; 778 bool privacy;
768 struct cfg80211_crypto_settings crypto; 779 struct cfg80211_crypto_settings crypto;
780 const u8 *key;
781 u8 key_len, key_idx;
769}; 782};
770 783
771/** 784/**
@@ -1223,9 +1236,10 @@ extern void wiphy_unregister(struct wiphy *wiphy);
1223 */ 1236 */
1224extern void wiphy_free(struct wiphy *wiphy); 1237extern void wiphy_free(struct wiphy *wiphy);
1225 1238
1226/* internal struct */ 1239/* internal structs */
1227struct cfg80211_conn; 1240struct cfg80211_conn;
1228struct cfg80211_internal_bss; 1241struct cfg80211_internal_bss;
1242struct cfg80211_cached_keys;
1229 1243
1230#define MAX_AUTH_BSSES 4 1244#define MAX_AUTH_BSSES 4
1231 1245
@@ -1267,6 +1281,7 @@ struct wireless_dev {
1267 CFG80211_SME_CONNECTED, 1281 CFG80211_SME_CONNECTED,
1268 } sme_state; 1282 } sme_state;
1269 struct cfg80211_conn *conn; 1283 struct cfg80211_conn *conn;
1284 struct cfg80211_cached_keys *connect_keys;
1270 1285
1271 struct list_head event_list; 1286 struct list_head event_list;
1272 spinlock_t event_lock; 1287 spinlock_t event_lock;
@@ -1280,6 +1295,7 @@ struct wireless_dev {
1280 struct { 1295 struct {
1281 struct cfg80211_ibss_params ibss; 1296 struct cfg80211_ibss_params ibss;
1282 struct cfg80211_connect_params connect; 1297 struct cfg80211_connect_params connect;
1298 struct cfg80211_cached_keys *keys;
1283 u8 *ie; 1299 u8 *ie;
1284 size_t ie_len; 1300 size_t ie_len;
1285 u8 bssid[ETH_ALEN]; 1301 u8 bssid[ETH_ALEN];
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 15d5a53b59a8..8e2220000e5c 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -57,7 +57,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
57 */ 57 */
58 if (auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1) 58 if (auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1)
59 ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, NULL, 0, 59 ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, NULL, 0,
60 sdata->u.ibss.bssid, 0); 60 sdata->u.ibss.bssid, NULL, 0, 0);
61} 61}
62 62
63static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, 63static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
@@ -494,7 +494,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
494 494
495 capability = WLAN_CAPABILITY_IBSS; 495 capability = WLAN_CAPABILITY_IBSS;
496 496
497 if (sdata->default_key) 497 if (ifibss->privacy)
498 capability |= WLAN_CAPABILITY_PRIVACY; 498 capability |= WLAN_CAPABILITY_PRIVACY;
499 else 499 else
500 sdata->drop_unencrypted = 0; 500 sdata->drop_unencrypted = 0;
@@ -524,9 +524,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
524 return; 524 return;
525 525
526 capability = WLAN_CAPABILITY_IBSS; 526 capability = WLAN_CAPABILITY_IBSS;
527 if (sdata->default_key) 527 if (ifibss->privacy)
528 capability |= WLAN_CAPABILITY_PRIVACY; 528 capability |= WLAN_CAPABILITY_PRIVACY;
529
530 if (ifibss->fixed_bssid) 529 if (ifibss->fixed_bssid)
531 bssid = ifibss->bssid; 530 bssid = ifibss->bssid;
532 if (ifibss->fixed_channel) 531 if (ifibss->fixed_channel)
@@ -872,6 +871,8 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
872 } else 871 } else
873 sdata->u.ibss.fixed_bssid = false; 872 sdata->u.ibss.fixed_bssid = false;
874 873
874 sdata->u.ibss.privacy = params->privacy;
875
875 sdata->vif.bss_conf.beacon_int = params->beacon_interval; 876 sdata->vif.bss_conf.beacon_int = params->beacon_interval;
876 877
877 sdata->u.ibss.channel = params->channel; 878 sdata->u.ibss.channel = params->channel;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 327aabc07abe..06b3411530f2 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -247,6 +247,9 @@ struct ieee80211_mgd_work {
247 247
248 int tries; 248 int tries;
249 249
250 u8 key[WLAN_KEY_LEN_WEP104];
251 u8 key_len, key_idx;
252
250 /* must be last */ 253 /* must be last */
251 u8 ie[0]; /* for auth or assoc frame, not probe */ 254 u8 ie[0]; /* for auth or assoc frame, not probe */
252}; 255};
@@ -321,6 +324,7 @@ struct ieee80211_if_ibss {
321 324
322 bool fixed_bssid; 325 bool fixed_bssid;
323 bool fixed_channel; 326 bool fixed_channel;
327 bool privacy;
324 328
325 u8 bssid[ETH_ALEN]; 329 u8 bssid[ETH_ALEN];
326 u8 ssid[IEEE80211_MAX_SSID_LEN]; 330 u8 ssid[IEEE80211_MAX_SSID_LEN];
@@ -1093,8 +1097,8 @@ int ieee80211_add_pending_skbs(struct ieee80211_local *local,
1093 1097
1094void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, 1098void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
1095 u16 transaction, u16 auth_alg, 1099 u16 transaction, u16 auth_alg,
1096 u8 *extra, size_t extra_len, 1100 u8 *extra, size_t extra_len, const u8 *bssid,
1097 const u8 *bssid, int encrypt); 1101 const u8 *key, u8 key_len, u8 key_idx);
1098int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, 1102int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1099 const u8 *ie, size_t ie_len); 1103 const u8 *ie, size_t ie_len);
1100void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, 1104void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index c9db9646025b..8e4a60497bba 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -954,7 +954,7 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
954 sdata->dev->name, wk->bss->cbss.bssid, wk->tries); 954 sdata->dev->name, wk->bss->cbss.bssid, wk->tries);
955 955
956 ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len, 956 ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len,
957 wk->bss->cbss.bssid, 0); 957 wk->bss->cbss.bssid, NULL, 0, 0);
958 wk->auth_transaction = 2; 958 wk->auth_transaction = 2;
959 959
960 wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; 960 wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
@@ -1176,7 +1176,8 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
1176 return; 1176 return;
1177 ieee80211_send_auth(sdata, 3, wk->auth_alg, 1177 ieee80211_send_auth(sdata, 3, wk->auth_alg,
1178 elems.challenge - 2, elems.challenge_len + 2, 1178 elems.challenge - 2, elems.challenge_len + 2,
1179 wk->bss->cbss.bssid, 1); 1179 wk->bss->cbss.bssid,
1180 wk->key, wk->key_len, wk->key_idx);
1180 wk->auth_transaction = 4; 1181 wk->auth_transaction = 4;
1181} 1182}
1182 1183
@@ -2175,6 +2176,12 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
2175 wk->ie_len = req->ie_len; 2176 wk->ie_len = req->ie_len;
2176 } 2177 }
2177 2178
2179 if (req->key && req->key_len) {
2180 wk->key_len = req->key_len;
2181 wk->key_idx = req->key_idx;
2182 memcpy(wk->key, req->key, req->key_len);
2183 }
2184
2178 ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); 2185 ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
2179 memcpy(wk->ssid, ssid + 2, ssid[1]); 2186 memcpy(wk->ssid, ssid + 2, ssid[1]);
2180 wk->ssid_len = ssid[1]; 2187 wk->ssid_len = ssid[1];
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 915e77769312..dbf66b52d38c 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -31,6 +31,7 @@
31#include "mesh.h" 31#include "mesh.h"
32#include "wme.h" 32#include "wme.h"
33#include "led.h" 33#include "led.h"
34#include "wep.h"
34 35
35/* privid for wiphys to determine whether they belong to us or not */ 36/* privid for wiphys to determine whether they belong to us or not */
36void *mac80211_wiphy_privid = &mac80211_wiphy_privid; 37void *mac80211_wiphy_privid = &mac80211_wiphy_privid;
@@ -804,12 +805,13 @@ u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
804 805
805void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, 806void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
806 u16 transaction, u16 auth_alg, 807 u16 transaction, u16 auth_alg,
807 u8 *extra, size_t extra_len, 808 u8 *extra, size_t extra_len, const u8 *bssid,
808 const u8 *bssid, int encrypt) 809 const u8 *key, u8 key_len, u8 key_idx)
809{ 810{
810 struct ieee80211_local *local = sdata->local; 811 struct ieee80211_local *local = sdata->local;
811 struct sk_buff *skb; 812 struct sk_buff *skb;
812 struct ieee80211_mgmt *mgmt; 813 struct ieee80211_mgmt *mgmt;
814 int err;
813 815
814 skb = dev_alloc_skb(local->hw.extra_tx_headroom + 816 skb = dev_alloc_skb(local->hw.extra_tx_headroom +
815 sizeof(*mgmt) + 6 + extra_len); 817 sizeof(*mgmt) + 6 + extra_len);
@@ -824,8 +826,6 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
824 memset(mgmt, 0, 24 + 6); 826 memset(mgmt, 0, 24 + 6);
825 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 827 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
826 IEEE80211_STYPE_AUTH); 828 IEEE80211_STYPE_AUTH);
827 if (encrypt)
828 mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
829 memcpy(mgmt->da, bssid, ETH_ALEN); 829 memcpy(mgmt->da, bssid, ETH_ALEN);
830 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 830 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
831 memcpy(mgmt->bssid, bssid, ETH_ALEN); 831 memcpy(mgmt->bssid, bssid, ETH_ALEN);
@@ -835,7 +835,13 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
835 if (extra) 835 if (extra)
836 memcpy(skb_put(skb, extra_len), extra, extra_len); 836 memcpy(skb_put(skb, extra_len), extra, extra_len);
837 837
838 ieee80211_tx_skb(sdata, skb, encrypt); 838 if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) {
839 mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
840 err = ieee80211_wep_encrypt(local, skb, key, key_len, key_idx);
841 WARN_ON(err);
842 }
843
844 ieee80211_tx_skb(sdata, skb, 0);
839} 845}
840 846
841int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, 847int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index 4fafb2d27c84..8a980f136941 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -144,9 +144,9 @@ void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
144 * 144 *
145 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) 145 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
146 */ 146 */
147static int ieee80211_wep_encrypt(struct ieee80211_local *local, 147int ieee80211_wep_encrypt(struct ieee80211_local *local,
148 struct sk_buff *skb, 148 struct sk_buff *skb,
149 const u8 *key, int keylen, int keyidx) 149 const u8 *key, int keylen, int keyidx)
150{ 150{
151 u8 *iv; 151 u8 *iv;
152 size_t len; 152 size_t len;
diff --git a/net/mac80211/wep.h b/net/mac80211/wep.h
index 85219ded8703..fe29d7e5759f 100644
--- a/net/mac80211/wep.h
+++ b/net/mac80211/wep.h
@@ -20,6 +20,9 @@ int ieee80211_wep_init(struct ieee80211_local *local);
20void ieee80211_wep_free(struct ieee80211_local *local); 20void ieee80211_wep_free(struct ieee80211_local *local);
21void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, 21void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
22 size_t klen, u8 *data, size_t data_len); 22 size_t klen, u8 *data, size_t data_len);
23int ieee80211_wep_encrypt(struct ieee80211_local *local,
24 struct sk_buff *skb,
25 const u8 *key, int keylen, int keyidx);
23int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, 26int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
24 size_t klen, u8 *data, size_t data_len); 27 size_t klen, u8 *data, size_t data_len);
25bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key); 28bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key);
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 1a78b3c70cf2..97cc5968b7d6 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -666,14 +666,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
666 wdev_lock(wdev); 666 wdev_lock(wdev);
667 switch (wdev->iftype) { 667 switch (wdev->iftype) {
668 case NL80211_IFTYPE_ADHOC: 668 case NL80211_IFTYPE_ADHOC:
669 if (wdev->wext.ibss.ssid_len) 669 cfg80211_ibss_wext_join(rdev, wdev);
670 __cfg80211_join_ibss(rdev, dev,
671 &wdev->wext.ibss);
672 break; 670 break;
673 case NL80211_IFTYPE_STATION: 671 case NL80211_IFTYPE_STATION:
674 if (wdev->wext.connect.ssid_len) 672 cfg80211_mgd_wext_connect(rdev, wdev);
675 __cfg80211_connect(rdev, dev,
676 &wdev->wext.connect);
677 break; 673 break;
678 default: 674 default:
679 break; 675 break;
@@ -690,6 +686,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
690 } 686 }
691 mutex_unlock(&rdev->devlist_mtx); 687 mutex_unlock(&rdev->devlist_mtx);
692 mutex_destroy(&wdev->mtx); 688 mutex_destroy(&wdev->mtx);
689#ifdef CONFIG_WIRELESS_EXT
690 kfree(wdev->wext.keys);
691#endif
693 break; 692 break;
694 case NETDEV_PRE_UP: 693 case NETDEV_PRE_UP:
695 if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) 694 if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
diff --git a/net/wireless/core.h b/net/wireless/core.h
index e46cd6eb61d7..2ec8ddbe57de 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -238,6 +238,12 @@ struct cfg80211_event {
238 }; 238 };
239}; 239};
240 240
241struct cfg80211_cached_keys {
242 struct key_params params[6];
243 u8 data[6][WLAN_MAX_KEY_LEN];
244 int def, defmgmt;
245};
246
241 247
242/* free object */ 248/* free object */
243extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev); 249extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev);
@@ -256,14 +262,18 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev,
256/* IBSS */ 262/* IBSS */
257int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, 263int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
258 struct net_device *dev, 264 struct net_device *dev,
259 struct cfg80211_ibss_params *params); 265 struct cfg80211_ibss_params *params,
266 struct cfg80211_cached_keys *connkeys);
260int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, 267int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
261 struct net_device *dev, 268 struct net_device *dev,
262 struct cfg80211_ibss_params *params); 269 struct cfg80211_ibss_params *params,
270 struct cfg80211_cached_keys *connkeys);
263void cfg80211_clear_ibss(struct net_device *dev, bool nowext); 271void cfg80211_clear_ibss(struct net_device *dev, bool nowext);
264int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, 272int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
265 struct net_device *dev, bool nowext); 273 struct net_device *dev, bool nowext);
266void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid); 274void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid);
275int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
276 struct wireless_dev *wdev);
267 277
268/* MLME */ 278/* MLME */
269int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, 279int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
@@ -272,12 +282,14 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
272 enum nl80211_auth_type auth_type, 282 enum nl80211_auth_type auth_type,
273 const u8 *bssid, 283 const u8 *bssid,
274 const u8 *ssid, int ssid_len, 284 const u8 *ssid, int ssid_len,
275 const u8 *ie, int ie_len); 285 const u8 *ie, int ie_len,
286 const u8 *key, int key_len, int key_idx);
276int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, 287int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
277 struct net_device *dev, struct ieee80211_channel *chan, 288 struct net_device *dev, struct ieee80211_channel *chan,
278 enum nl80211_auth_type auth_type, const u8 *bssid, 289 enum nl80211_auth_type auth_type, const u8 *bssid,
279 const u8 *ssid, int ssid_len, 290 const u8 *ssid, int ssid_len,
280 const u8 *ie, int ie_len); 291 const u8 *ie, int ie_len,
292 const u8 *key, int key_len, int key_idx);
281int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, 293int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
282 struct net_device *dev, 294 struct net_device *dev,
283 struct ieee80211_channel *chan, 295 struct ieee80211_channel *chan,
@@ -310,10 +322,12 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
310/* SME */ 322/* SME */
311int __cfg80211_connect(struct cfg80211_registered_device *rdev, 323int __cfg80211_connect(struct cfg80211_registered_device *rdev,
312 struct net_device *dev, 324 struct net_device *dev,
313 struct cfg80211_connect_params *connect); 325 struct cfg80211_connect_params *connect,
326 struct cfg80211_cached_keys *connkeys);
314int cfg80211_connect(struct cfg80211_registered_device *rdev, 327int cfg80211_connect(struct cfg80211_registered_device *rdev,
315 struct net_device *dev, 328 struct net_device *dev,
316 struct cfg80211_connect_params *connect); 329 struct cfg80211_connect_params *connect,
330 struct cfg80211_cached_keys *connkeys);
317int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, 331int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
318 struct net_device *dev, u16 reason, 332 struct net_device *dev, u16 reason,
319 bool wextev); 333 bool wextev);
@@ -323,11 +337,14 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
323void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid, 337void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
324 const u8 *req_ie, size_t req_ie_len, 338 const u8 *req_ie, size_t req_ie_len,
325 const u8 *resp_ie, size_t resp_ie_len); 339 const u8 *resp_ie, size_t resp_ie_len);
340int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
341 struct wireless_dev *wdev);
326 342
327void cfg80211_conn_work(struct work_struct *work); 343void cfg80211_conn_work(struct work_struct *work);
328 344
329/* internal helpers */ 345/* internal helpers */
330int cfg80211_validate_key_settings(struct key_params *params, int key_idx, 346int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
347 struct key_params *params, int key_idx,
331 const u8 *mac_addr); 348 const u8 *mac_addr);
332void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, 349void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
333 size_t ie_len, u16 reason, bool from_ap); 350 size_t ie_len, u16 reason, bool from_ap);
@@ -335,5 +352,6 @@ void cfg80211_sme_scan_done(struct net_device *dev);
335void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len); 352void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
336void cfg80211_sme_disassoc(struct net_device *dev, int idx); 353void cfg80211_sme_disassoc(struct net_device *dev, int idx);
337void __cfg80211_scan_done(struct work_struct *wk); 354void __cfg80211_scan_done(struct work_struct *wk);
355void cfg80211_upload_connect_keys(struct wireless_dev *wdev);
338 356
339#endif /* __NET_WIRELESS_CORE_H */ 357#endif /* __NET_WIRELESS_CORE_H */
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 99ef9364b7e8..9394e78cd11f 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -39,6 +39,8 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
39 cfg80211_hold_bss(bss_from_pub(bss)); 39 cfg80211_hold_bss(bss_from_pub(bss));
40 wdev->current_bss = bss_from_pub(bss); 40 wdev->current_bss = bss_from_pub(bss);
41 41
42 cfg80211_upload_connect_keys(wdev);
43
42 nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, 44 nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid,
43 GFP_KERNEL); 45 GFP_KERNEL);
44#ifdef CONFIG_WIRELESS_EXT 46#ifdef CONFIG_WIRELESS_EXT
@@ -71,7 +73,8 @@ EXPORT_SYMBOL(cfg80211_ibss_joined);
71 73
72int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, 74int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
73 struct net_device *dev, 75 struct net_device *dev,
74 struct cfg80211_ibss_params *params) 76 struct cfg80211_ibss_params *params,
77 struct cfg80211_cached_keys *connkeys)
75{ 78{
76 struct wireless_dev *wdev = dev->ieee80211_ptr; 79 struct wireless_dev *wdev = dev->ieee80211_ptr;
77 int err; 80 int err;
@@ -81,13 +84,18 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
81 if (wdev->ssid_len) 84 if (wdev->ssid_len)
82 return -EALREADY; 85 return -EALREADY;
83 86
87 if (WARN_ON(wdev->connect_keys))
88 kfree(wdev->connect_keys);
89 wdev->connect_keys = connkeys;
90
84#ifdef CONFIG_WIRELESS_EXT 91#ifdef CONFIG_WIRELESS_EXT
85 wdev->wext.ibss.channel = params->channel; 92 wdev->wext.ibss.channel = params->channel;
86#endif 93#endif
87 err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); 94 err = rdev->ops->join_ibss(&rdev->wiphy, dev, params);
88 95 if (err) {
89 if (err) 96 wdev->connect_keys = NULL;
90 return err; 97 return err;
98 }
91 99
92 memcpy(wdev->ssid, params->ssid, params->ssid_len); 100 memcpy(wdev->ssid, params->ssid, params->ssid_len);
93 wdev->ssid_len = params->ssid_len; 101 wdev->ssid_len = params->ssid_len;
@@ -97,13 +105,14 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
97 105
98int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, 106int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
99 struct net_device *dev, 107 struct net_device *dev,
100 struct cfg80211_ibss_params *params) 108 struct cfg80211_ibss_params *params,
109 struct cfg80211_cached_keys *connkeys)
101{ 110{
102 struct wireless_dev *wdev = dev->ieee80211_ptr; 111 struct wireless_dev *wdev = dev->ieee80211_ptr;
103 int err; 112 int err;
104 113
105 wdev_lock(wdev); 114 wdev_lock(wdev);
106 err = __cfg80211_join_ibss(rdev, dev, params); 115 err = __cfg80211_join_ibss(rdev, dev, params, connkeys);
107 wdev_unlock(wdev); 116 wdev_unlock(wdev);
108 117
109 return err; 118 return err;
@@ -112,9 +121,22 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
112static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) 121static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
113{ 122{
114 struct wireless_dev *wdev = dev->ieee80211_ptr; 123 struct wireless_dev *wdev = dev->ieee80211_ptr;
124 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
125 int i;
115 126
116 ASSERT_WDEV_LOCK(wdev); 127 ASSERT_WDEV_LOCK(wdev);
117 128
129 kfree(wdev->connect_keys);
130 wdev->connect_keys = NULL;
131
132 /*
133 * Delete all the keys ... pairwise keys can't really
134 * exist any more anyway, but default keys might.
135 */
136 if (rdev->ops->del_key)
137 for (i = 0; i < 6; i++)
138 rdev->ops->del_key(wdev->wiphy, dev, i, NULL);
139
118 if (wdev->current_bss) { 140 if (wdev->current_bss) {
119 cfg80211_unhold_bss(wdev->current_bss); 141 cfg80211_unhold_bss(wdev->current_bss);
120 cfg80211_put_bss(&wdev->current_bss->pub); 142 cfg80211_put_bss(&wdev->current_bss->pub);
@@ -172,11 +194,14 @@ int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
172} 194}
173 195
174#ifdef CONFIG_WIRELESS_EXT 196#ifdef CONFIG_WIRELESS_EXT
175static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, 197int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
176 struct wireless_dev *wdev) 198 struct wireless_dev *wdev)
177{ 199{
200 struct cfg80211_cached_keys *ck = NULL;
178 enum ieee80211_band band; 201 enum ieee80211_band band;
179 int i; 202 int i, err;
203
204 ASSERT_WDEV_LOCK(wdev);
180 205
181 if (!wdev->wext.ibss.beacon_interval) 206 if (!wdev->wext.ibss.beacon_interval)
182 wdev->wext.ibss.beacon_interval = 100; 207 wdev->wext.ibss.beacon_interval = 100;
@@ -216,8 +241,24 @@ static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
216 if (!netif_running(wdev->netdev)) 241 if (!netif_running(wdev->netdev))
217 return 0; 242 return 0;
218 243
219 return cfg80211_join_ibss(wiphy_to_dev(wdev->wiphy), 244 if (wdev->wext.keys)
220 wdev->netdev, &wdev->wext.ibss); 245 wdev->wext.keys->def = wdev->wext.default_key;
246
247 wdev->wext.ibss.privacy = wdev->wext.default_key != -1;
248
249 if (wdev->wext.keys) {
250 ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL);
251 if (!ck)
252 return -ENOMEM;
253 for (i = 0; i < 6; i++)
254 ck->params[i].key = ck->data[i];
255 }
256 err = __cfg80211_join_ibss(rdev, wdev->netdev,
257 &wdev->wext.ibss, ck);
258 if (err)
259 kfree(ck);
260
261 return err;
221} 262}
222 263
223int cfg80211_ibss_wext_siwfreq(struct net_device *dev, 264int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
@@ -265,7 +306,11 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
265 wdev->wext.ibss.channel_fixed = false; 306 wdev->wext.ibss.channel_fixed = false;
266 } 307 }
267 308
268 return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); 309 wdev_lock(wdev);
310 err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
311 wdev_unlock(wdev);
312
313 return err;
269} 314}
270/* temporary symbol - mark GPL - in the future the handler won't be */ 315/* temporary symbol - mark GPL - in the future the handler won't be */
271EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwfreq); 316EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwfreq);
@@ -333,7 +378,11 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
333 memcpy(wdev->wext.ibss.ssid, ssid, len); 378 memcpy(wdev->wext.ibss.ssid, ssid, len);
334 wdev->wext.ibss.ssid_len = len; 379 wdev->wext.ibss.ssid_len = len;
335 380
336 return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); 381 wdev_lock(wdev);
382 err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
383 wdev_unlock(wdev);
384
385 return err;
337} 386}
338/* temporary symbol - mark GPL - in the future the handler won't be */ 387/* temporary symbol - mark GPL - in the future the handler won't be */
339EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwessid); 388EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwessid);
@@ -414,7 +463,11 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
414 } else 463 } else
415 wdev->wext.ibss.bssid = NULL; 464 wdev->wext.ibss.bssid = NULL;
416 465
417 return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); 466 wdev_lock(wdev);
467 err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
468 wdev_unlock(wdev);
469
470 return err;
418} 471}
419/* temporary symbol - mark GPL - in the future the handler won't be */ 472/* temporary symbol - mark GPL - in the future the handler won't be */
420EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwap); 473EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwap);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 1b2ca1fea7a1..8e4ce2fdf862 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -328,7 +328,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
328 enum nl80211_auth_type auth_type, 328 enum nl80211_auth_type auth_type,
329 const u8 *bssid, 329 const u8 *bssid,
330 const u8 *ssid, int ssid_len, 330 const u8 *ssid, int ssid_len,
331 const u8 *ie, int ie_len) 331 const u8 *ie, int ie_len,
332 const u8 *key, int key_len, int key_idx)
332{ 333{
333 struct wireless_dev *wdev = dev->ieee80211_ptr; 334 struct wireless_dev *wdev = dev->ieee80211_ptr;
334 struct cfg80211_auth_request req; 335 struct cfg80211_auth_request req;
@@ -337,6 +338,10 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
337 338
338 ASSERT_WDEV_LOCK(wdev); 339 ASSERT_WDEV_LOCK(wdev);
339 340
341 if (auth_type == NL80211_AUTHTYPE_SHARED_KEY)
342 if (!key || !key_len || key_idx < 0 || key_idx > 4)
343 return -EINVAL;
344
340 if (wdev->current_bss && 345 if (wdev->current_bss &&
341 memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0) 346 memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0)
342 return -EALREADY; 347 return -EALREADY;
@@ -359,6 +364,9 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
359 req.auth_type = auth_type; 364 req.auth_type = auth_type;
360 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, 365 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
361 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); 366 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
367 req.key = key;
368 req.key_len = key_len;
369 req.key_idx = key_idx;
362 if (!req.bss) 370 if (!req.bss)
363 return -ENOENT; 371 return -ENOENT;
364 372
@@ -396,13 +404,15 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
396 struct net_device *dev, struct ieee80211_channel *chan, 404 struct net_device *dev, struct ieee80211_channel *chan,
397 enum nl80211_auth_type auth_type, const u8 *bssid, 405 enum nl80211_auth_type auth_type, const u8 *bssid,
398 const u8 *ssid, int ssid_len, 406 const u8 *ssid, int ssid_len,
399 const u8 *ie, int ie_len) 407 const u8 *ie, int ie_len,
408 const u8 *key, int key_len, int key_idx)
400{ 409{
401 int err; 410 int err;
402 411
403 wdev_lock(dev->ieee80211_ptr); 412 wdev_lock(dev->ieee80211_ptr);
404 err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, 413 err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
405 ssid, ssid_len, ie, ie_len); 414 ssid, ssid_len, ie, ie_len,
415 key, key_len, key_idx);
406 wdev_unlock(dev->ieee80211_ptr); 416 wdev_unlock(dev->ieee80211_ptr);
407 417
408 return err; 418 return err;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 50cf59316292..45c5f9c8e51b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -138,8 +138,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
138/* policy for the attributes */ 138/* policy for the attributes */
139static struct nla_policy 139static struct nla_policy
140nl80211_key_policy[NL80211_KEY_MAX + 1] __read_mostly = { 140nl80211_key_policy[NL80211_KEY_MAX + 1] __read_mostly = {
141 [NL80211_KEY_DATA] = { .type = NLA_BINARY, 141 [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
142 .len = WLAN_MAX_KEY_LEN },
143 [NL80211_KEY_IDX] = { .type = NLA_U8 }, 142 [NL80211_KEY_IDX] = { .type = NLA_U8 },
144 [NL80211_KEY_CIPHER] = { .type = NLA_U32 }, 143 [NL80211_KEY_CIPHER] = { .type = NLA_U32 },
145 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, 144 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
@@ -305,6 +304,83 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
305 return 0; 304 return 0;
306} 305}
307 306
307static struct cfg80211_cached_keys *
308nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
309 struct nlattr *keys)
310{
311 struct key_parse parse;
312 struct nlattr *key;
313 struct cfg80211_cached_keys *result;
314 int rem, err, def = 0;
315
316 result = kzalloc(sizeof(*result), GFP_KERNEL);
317 if (!result)
318 return ERR_PTR(-ENOMEM);
319
320 result->def = -1;
321 result->defmgmt = -1;
322
323 nla_for_each_nested(key, keys, rem) {
324 memset(&parse, 0, sizeof(parse));
325 parse.idx = -1;
326
327 err = nl80211_parse_key_new(key, &parse);
328 if (err)
329 goto error;
330 err = -EINVAL;
331 if (!parse.p.key)
332 goto error;
333 if (parse.idx < 0 || parse.idx > 4)
334 goto error;
335 if (parse.def) {
336 if (def)
337 goto error;
338 def = 1;
339 result->def = parse.idx;
340 } else if (parse.defmgmt)
341 goto error;
342 err = cfg80211_validate_key_settings(rdev, &parse.p,
343 parse.idx, NULL);
344 if (err)
345 goto error;
346 result->params[parse.idx].cipher = parse.p.cipher;
347 result->params[parse.idx].key_len = parse.p.key_len;
348 result->params[parse.idx].key = result->data[parse.idx];
349 memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len);
350 }
351
352 return result;
353 error:
354 kfree(result);
355 return ERR_PTR(err);
356}
357
358static int nl80211_key_allowed(struct wireless_dev *wdev)
359{
360 ASSERT_WDEV_LOCK(wdev);
361
362 if (!netif_running(wdev->netdev))
363 return -ENETDOWN;
364
365 switch (wdev->iftype) {
366 case NL80211_IFTYPE_AP:
367 case NL80211_IFTYPE_AP_VLAN:
368 break;
369 case NL80211_IFTYPE_ADHOC:
370 if (!wdev->current_bss)
371 return -ENOLINK;
372 break;
373 case NL80211_IFTYPE_STATION:
374 if (wdev->sme_state != CFG80211_SME_CONNECTED)
375 return -ENOLINK;
376 break;
377 default:
378 return -EINVAL;
379 }
380
381 return 0;
382}
383
308static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, 384static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
309 struct cfg80211_registered_device *dev) 385 struct cfg80211_registered_device *dev)
310{ 386{
@@ -1212,7 +1288,11 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
1212 goto out; 1288 goto out;
1213 } 1289 }
1214 1290
1215 err = func(&rdev->wiphy, dev, key.idx); 1291 wdev_lock(dev->ieee80211_ptr);
1292 err = nl80211_key_allowed(dev->ieee80211_ptr);
1293 if (!err)
1294 err = func(&rdev->wiphy, dev, key.idx);
1295
1216#ifdef CONFIG_WIRELESS_EXT 1296#ifdef CONFIG_WIRELESS_EXT
1217 if (!err) { 1297 if (!err) {
1218 if (func == rdev->ops->set_default_key) 1298 if (func == rdev->ops->set_default_key)
@@ -1221,6 +1301,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
1221 dev->ieee80211_ptr->wext.default_mgmt_key = key.idx; 1301 dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
1222 } 1302 }
1223#endif 1303#endif
1304 wdev_unlock(dev->ieee80211_ptr);
1224 1305
1225 out: 1306 out:
1226 cfg80211_unlock_rdev(rdev); 1307 cfg80211_unlock_rdev(rdev);
@@ -1235,7 +1316,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
1235static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) 1316static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1236{ 1317{
1237 struct cfg80211_registered_device *rdev; 1318 struct cfg80211_registered_device *rdev;
1238 int err, i; 1319 int err;
1239 struct net_device *dev; 1320 struct net_device *dev;
1240 struct key_parse key; 1321 struct key_parse key;
1241 u8 *mac_addr = NULL; 1322 u8 *mac_addr = NULL;
@@ -1250,29 +1331,28 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1250 if (info->attrs[NL80211_ATTR_MAC]) 1331 if (info->attrs[NL80211_ATTR_MAC])
1251 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1332 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1252 1333
1253 if (cfg80211_validate_key_settings(&key.p, key.idx, mac_addr))
1254 return -EINVAL;
1255
1256 rtnl_lock(); 1334 rtnl_lock();
1257 1335
1258 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); 1336 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
1259 if (err) 1337 if (err)
1260 goto unlock_rtnl; 1338 goto unlock_rtnl;
1261 1339
1262 for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) 1340 if (!rdev->ops->add_key) {
1263 if (key.p.cipher == rdev->wiphy.cipher_suites[i]) 1341 err = -EOPNOTSUPP;
1264 break;
1265 if (i == rdev->wiphy.n_cipher_suites) {
1266 err = -EINVAL;
1267 goto out; 1342 goto out;
1268 } 1343 }
1269 1344
1270 if (!rdev->ops->add_key) { 1345 if (cfg80211_validate_key_settings(rdev, &key.p, key.idx, mac_addr)) {
1271 err = -EOPNOTSUPP; 1346 err = -EINVAL;
1272 goto out; 1347 goto out;
1273 } 1348 }
1274 1349
1275 err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx, mac_addr, &key.p); 1350 wdev_lock(dev->ieee80211_ptr);
1351 err = nl80211_key_allowed(dev->ieee80211_ptr);
1352 if (!err)
1353 err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx,
1354 mac_addr, &key.p);
1355 wdev_unlock(dev->ieee80211_ptr);
1276 1356
1277 out: 1357 out:
1278 cfg80211_unlock_rdev(rdev); 1358 cfg80211_unlock_rdev(rdev);
@@ -1309,7 +1389,10 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
1309 goto out; 1389 goto out;
1310 } 1390 }
1311 1391
1312 err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr); 1392 wdev_lock(dev->ieee80211_ptr);
1393 err = nl80211_key_allowed(dev->ieee80211_ptr);
1394 if (!err)
1395 err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr);
1313 1396
1314#ifdef CONFIG_WIRELESS_EXT 1397#ifdef CONFIG_WIRELESS_EXT
1315 if (!err) { 1398 if (!err) {
@@ -1319,6 +1402,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
1319 dev->ieee80211_ptr->wext.default_mgmt_key = -1; 1402 dev->ieee80211_ptr->wext.default_mgmt_key = -1;
1320 } 1403 }
1321#endif 1404#endif
1405 wdev_unlock(dev->ieee80211_ptr);
1322 1406
1323 out: 1407 out:
1324 cfg80211_unlock_rdev(rdev); 1408 cfg80211_unlock_rdev(rdev);
@@ -3159,6 +3243,7 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3159 const u8 *bssid, *ssid, *ie = NULL; 3243 const u8 *bssid, *ssid, *ie = NULL;
3160 int err, ssid_len, ie_len = 0; 3244 int err, ssid_len, ie_len = 0;
3161 enum nl80211_auth_type auth_type; 3245 enum nl80211_auth_type auth_type;
3246 struct key_parse key;
3162 3247
3163 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 3248 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3164 return -EINVAL; 3249 return -EINVAL;
@@ -3175,6 +3260,25 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3175 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) 3260 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
3176 return -EINVAL; 3261 return -EINVAL;
3177 3262
3263 err = nl80211_parse_key(info, &key);
3264 if (err)
3265 return err;
3266
3267 if (key.idx >= 0) {
3268 if (!key.p.key || !key.p.key_len)
3269 return -EINVAL;
3270 if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 ||
3271 key.p.key_len != WLAN_KEY_LEN_WEP40) &&
3272 (key.p.cipher != WLAN_CIPHER_SUITE_WEP104 ||
3273 key.p.key_len != WLAN_KEY_LEN_WEP104))
3274 return -EINVAL;
3275 if (key.idx > 4)
3276 return -EINVAL;
3277 } else {
3278 key.p.key_len = 0;
3279 key.p.key = NULL;
3280 }
3281
3178 rtnl_lock(); 3282 rtnl_lock();
3179 3283
3180 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); 3284 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
@@ -3219,7 +3323,8 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3219 } 3323 }
3220 3324
3221 err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, 3325 err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
3222 ssid, ssid_len, ie, ie_len); 3326 ssid, ssid_len, ie, ie_len,
3327 key.p.key, key.p.key_len, key.idx);
3223 3328
3224out: 3329out:
3225 cfg80211_unlock_rdev(rdev); 3330 cfg80211_unlock_rdev(rdev);
@@ -3506,6 +3611,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
3506 struct net_device *dev; 3611 struct net_device *dev;
3507 struct cfg80211_ibss_params ibss; 3612 struct cfg80211_ibss_params ibss;
3508 struct wiphy *wiphy; 3613 struct wiphy *wiphy;
3614 struct cfg80211_cached_keys *connkeys = NULL;
3509 int err; 3615 int err;
3510 3616
3511 memset(&ibss, 0, sizeof(ibss)); 3617 memset(&ibss, 0, sizeof(ibss));
@@ -3570,13 +3676,26 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
3570 } 3676 }
3571 3677
3572 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; 3678 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
3679 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
3680
3681 if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
3682 connkeys = nl80211_parse_connkeys(rdev,
3683 info->attrs[NL80211_ATTR_KEYS]);
3684 if (IS_ERR(connkeys)) {
3685 err = PTR_ERR(connkeys);
3686 connkeys = NULL;
3687 goto out;
3688 }
3689 }
3573 3690
3574 err = cfg80211_join_ibss(rdev, dev, &ibss); 3691 err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
3575 3692
3576out: 3693out:
3577 cfg80211_unlock_rdev(rdev); 3694 cfg80211_unlock_rdev(rdev);
3578 dev_put(dev); 3695 dev_put(dev);
3579unlock_rtnl: 3696unlock_rtnl:
3697 if (err)
3698 kfree(connkeys);
3580 rtnl_unlock(); 3699 rtnl_unlock();
3581 return err; 3700 return err;
3582} 3701}
@@ -3746,6 +3865,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
3746 struct net_device *dev; 3865 struct net_device *dev;
3747 struct cfg80211_connect_params connect; 3866 struct cfg80211_connect_params connect;
3748 struct wiphy *wiphy; 3867 struct wiphy *wiphy;
3868 struct cfg80211_cached_keys *connkeys = NULL;
3749 int err; 3869 int err;
3750 3870
3751 memset(&connect, 0, sizeof(connect)); 3871 memset(&connect, 0, sizeof(connect));
@@ -3810,12 +3930,24 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
3810 } 3930 }
3811 } 3931 }
3812 3932
3813 err = cfg80211_connect(rdev, dev, &connect); 3933 if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
3934 connkeys = nl80211_parse_connkeys(rdev,
3935 info->attrs[NL80211_ATTR_KEYS]);
3936 if (IS_ERR(connkeys)) {
3937 err = PTR_ERR(connkeys);
3938 connkeys = NULL;
3939 goto out;
3940 }
3941 }
3942
3943 err = cfg80211_connect(rdev, dev, &connect, connkeys);
3814 3944
3815out: 3945out:
3816 cfg80211_unlock_rdev(rdev); 3946 cfg80211_unlock_rdev(rdev);
3817 dev_put(dev); 3947 dev_put(dev);
3818unlock_rtnl: 3948unlock_rtnl:
3949 if (err)
3950 kfree(connkeys);
3819 rtnl_unlock(); 3951 rtnl_unlock();
3820 return err; 3952 return err;
3821} 3953}
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 79ca56cbfd36..d635a99dba51 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -125,7 +125,9 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
125 params->channel, params->auth_type, 125 params->channel, params->auth_type,
126 params->bssid, 126 params->bssid,
127 params->ssid, params->ssid_len, 127 params->ssid, params->ssid_len,
128 NULL, 0); 128 NULL, 0,
129 params->key, params->key_len,
130 params->key_idx);
129 case CFG80211_CONN_ASSOCIATE_NEXT: 131 case CFG80211_CONN_ASSOCIATE_NEXT:
130 BUG_ON(!rdev->ops->assoc); 132 BUG_ON(!rdev->ops->assoc);
131 wdev->conn->state = CFG80211_CONN_ASSOCIATING; 133 wdev->conn->state = CFG80211_CONN_ASSOCIATING;
@@ -279,8 +281,12 @@ void cfg80211_sme_rx_auth(struct net_device *dev,
279 /* select automatically between only open, shared, leap */ 281 /* select automatically between only open, shared, leap */
280 switch (wdev->conn->params.auth_type) { 282 switch (wdev->conn->params.auth_type) {
281 case NL80211_AUTHTYPE_OPEN_SYSTEM: 283 case NL80211_AUTHTYPE_OPEN_SYSTEM:
282 wdev->conn->params.auth_type = 284 if (wdev->connect_keys)
283 NL80211_AUTHTYPE_SHARED_KEY; 285 wdev->conn->params.auth_type =
286 NL80211_AUTHTYPE_SHARED_KEY;
287 else
288 wdev->conn->params.auth_type =
289 NL80211_AUTHTYPE_NETWORK_EAP;
284 break; 290 break;
285 case NL80211_AUTHTYPE_SHARED_KEY: 291 case NL80211_AUTHTYPE_SHARED_KEY:
286 wdev->conn->params.auth_type = 292 wdev->conn->params.auth_type =
@@ -353,10 +359,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
353#endif 359#endif
354 360
355 if (status == WLAN_STATUS_SUCCESS && 361 if (status == WLAN_STATUS_SUCCESS &&
356 wdev->sme_state == CFG80211_SME_IDLE) { 362 wdev->sme_state == CFG80211_SME_IDLE)
357 wdev->sme_state = CFG80211_SME_CONNECTED; 363 goto success;
358 return;
359 }
360 364
361 if (wdev->sme_state != CFG80211_SME_CONNECTING) 365 if (wdev->sme_state != CFG80211_SME_CONNECTING)
362 return; 366 return;
@@ -370,24 +374,29 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
370 if (wdev->conn) 374 if (wdev->conn)
371 wdev->conn->state = CFG80211_CONN_IDLE; 375 wdev->conn->state = CFG80211_CONN_IDLE;
372 376
373 if (status == WLAN_STATUS_SUCCESS) { 377 if (status != WLAN_STATUS_SUCCESS) {
374 bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
375 wdev->ssid, wdev->ssid_len,
376 WLAN_CAPABILITY_ESS,
377 WLAN_CAPABILITY_ESS);
378
379 if (WARN_ON(!bss))
380 return;
381
382 cfg80211_hold_bss(bss_from_pub(bss));
383 wdev->current_bss = bss_from_pub(bss);
384
385 wdev->sme_state = CFG80211_SME_CONNECTED;
386 } else {
387 wdev->sme_state = CFG80211_SME_IDLE; 378 wdev->sme_state = CFG80211_SME_IDLE;
388 kfree(wdev->conn); 379 kfree(wdev->conn);
389 wdev->conn = NULL; 380 wdev->conn = NULL;
381 kfree(wdev->connect_keys);
382 wdev->connect_keys = NULL;
383 return;
390 } 384 }
385
386 bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
387 wdev->ssid, wdev->ssid_len,
388 WLAN_CAPABILITY_ESS,
389 WLAN_CAPABILITY_ESS);
390
391 if (WARN_ON(!bss))
392 return;
393
394 cfg80211_hold_bss(bss_from_pub(bss));
395 wdev->current_bss = bss_from_pub(bss);
396
397 success:
398 wdev->sme_state = CFG80211_SME_CONNECTED;
399 cfg80211_upload_connect_keys(wdev);
391} 400}
392 401
393void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, 402void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
@@ -516,6 +525,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
516 size_t ie_len, u16 reason, bool from_ap) 525 size_t ie_len, u16 reason, bool from_ap)
517{ 526{
518 struct wireless_dev *wdev = dev->ieee80211_ptr; 527 struct wireless_dev *wdev = dev->ieee80211_ptr;
528 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
529 int i;
519#ifdef CONFIG_WIRELESS_EXT 530#ifdef CONFIG_WIRELESS_EXT
520 union iwreq_data wrqu; 531 union iwreq_data wrqu;
521#endif 532#endif
@@ -543,8 +554,15 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
543 wdev->conn = NULL; 554 wdev->conn = NULL;
544 } 555 }
545 556
546 nl80211_send_disconnected(wiphy_to_dev(wdev->wiphy), dev, 557 nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap);
547 reason, ie, ie_len, from_ap); 558
559 /*
560 * Delete all the keys ... pairwise keys can't really
561 * exist any more anyway, but default keys might.
562 */
563 if (rdev->ops->del_key)
564 for (i = 0; i < 6; i++)
565 rdev->ops->del_key(wdev->wiphy, dev, i, NULL);
548 566
549#ifdef CONFIG_WIRELESS_EXT 567#ifdef CONFIG_WIRELESS_EXT
550 memset(&wrqu, 0, sizeof(wrqu)); 568 memset(&wrqu, 0, sizeof(wrqu));
@@ -580,7 +598,8 @@ EXPORT_SYMBOL(cfg80211_disconnected);
580 598
581int __cfg80211_connect(struct cfg80211_registered_device *rdev, 599int __cfg80211_connect(struct cfg80211_registered_device *rdev,
582 struct net_device *dev, 600 struct net_device *dev,
583 struct cfg80211_connect_params *connect) 601 struct cfg80211_connect_params *connect,
602 struct cfg80211_cached_keys *connkeys)
584{ 603{
585 struct wireless_dev *wdev = dev->ieee80211_ptr; 604 struct wireless_dev *wdev = dev->ieee80211_ptr;
586 int err; 605 int err;
@@ -590,6 +609,24 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
590 if (wdev->sme_state != CFG80211_SME_IDLE) 609 if (wdev->sme_state != CFG80211_SME_IDLE)
591 return -EALREADY; 610 return -EALREADY;
592 611
612 if (WARN_ON(wdev->connect_keys)) {
613 kfree(wdev->connect_keys);
614 wdev->connect_keys = NULL;
615 }
616
617 if (connkeys && connkeys->def >= 0) {
618 int idx;
619
620 idx = connkeys->def;
621 /* If given a WEP key we may need it for shared key auth */
622 if (connkeys->params[idx].cipher == WLAN_CIPHER_SUITE_WEP40 ||
623 connkeys->params[idx].cipher == WLAN_CIPHER_SUITE_WEP104) {
624 connect->key_idx = idx;
625 connect->key = connkeys->params[idx].key;
626 connect->key_len = connkeys->params[idx].key_len;
627 }
628 }
629
593 if (!rdev->ops->connect) { 630 if (!rdev->ops->connect) {
594 if (!rdev->ops->auth || !rdev->ops->assoc) 631 if (!rdev->ops->auth || !rdev->ops->assoc)
595 return -EOPNOTSUPP; 632 return -EOPNOTSUPP;
@@ -640,6 +677,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
640 cfg80211_get_conn_bss(wdev); 677 cfg80211_get_conn_bss(wdev);
641 678
642 wdev->sme_state = CFG80211_SME_CONNECTING; 679 wdev->sme_state = CFG80211_SME_CONNECTING;
680 wdev->connect_keys = connkeys;
643 681
644 /* we're good if we have both BSSID and channel */ 682 /* we're good if we have both BSSID and channel */
645 if (wdev->conn->params.bssid && wdev->conn->params.channel) { 683 if (wdev->conn->params.bssid && wdev->conn->params.channel) {
@@ -662,13 +700,16 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
662 kfree(wdev->conn); 700 kfree(wdev->conn);
663 wdev->conn = NULL; 701 wdev->conn = NULL;
664 wdev->sme_state = CFG80211_SME_IDLE; 702 wdev->sme_state = CFG80211_SME_IDLE;
703 wdev->connect_keys = NULL;
665 } 704 }
666 705
667 return err; 706 return err;
668 } else { 707 } else {
669 wdev->sme_state = CFG80211_SME_CONNECTING; 708 wdev->sme_state = CFG80211_SME_CONNECTING;
709 wdev->connect_keys = connkeys;
670 err = rdev->ops->connect(&rdev->wiphy, dev, connect); 710 err = rdev->ops->connect(&rdev->wiphy, dev, connect);
671 if (err) { 711 if (err) {
712 wdev->connect_keys = NULL;
672 wdev->sme_state = CFG80211_SME_IDLE; 713 wdev->sme_state = CFG80211_SME_IDLE;
673 return err; 714 return err;
674 } 715 }
@@ -682,12 +723,13 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
682 723
683int cfg80211_connect(struct cfg80211_registered_device *rdev, 724int cfg80211_connect(struct cfg80211_registered_device *rdev,
684 struct net_device *dev, 725 struct net_device *dev,
685 struct cfg80211_connect_params *connect) 726 struct cfg80211_connect_params *connect,
727 struct cfg80211_cached_keys *connkeys)
686{ 728{
687 int err; 729 int err;
688 730
689 wdev_lock(dev->ieee80211_ptr); 731 wdev_lock(dev->ieee80211_ptr);
690 err = __cfg80211_connect(rdev, dev, connect); 732 err = __cfg80211_connect(rdev, dev, connect, connkeys);
691 wdev_unlock(dev->ieee80211_ptr); 733 wdev_unlock(dev->ieee80211_ptr);
692 734
693 return err; 735 return err;
@@ -704,6 +746,9 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
704 if (wdev->sme_state == CFG80211_SME_IDLE) 746 if (wdev->sme_state == CFG80211_SME_IDLE)
705 return -EINVAL; 747 return -EINVAL;
706 748
749 kfree(wdev->connect_keys);
750 wdev->connect_keys = NULL;
751
707 if (!rdev->ops->disconnect) { 752 if (!rdev->ops->disconnect) {
708 if (!rdev->ops->deauth) 753 if (!rdev->ops->deauth)
709 return -EOPNOTSUPP; 754 return -EOPNOTSUPP;
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 28f8f96801d4..4bab380a1204 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -141,9 +141,12 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy)
141 set_mandatory_flags_band(wiphy->bands[band], band); 141 set_mandatory_flags_band(wiphy->bands[band], band);
142} 142}
143 143
144int cfg80211_validate_key_settings(struct key_params *params, int key_idx, 144int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
145 struct key_params *params, int key_idx,
145 const u8 *mac_addr) 146 const u8 *mac_addr)
146{ 147{
148 int i;
149
147 if (key_idx > 5) 150 if (key_idx > 5)
148 return -EINVAL; 151 return -EINVAL;
149 152
@@ -197,6 +200,12 @@ int cfg80211_validate_key_settings(struct key_params *params, int key_idx,
197 } 200 }
198 } 201 }
199 202
203 for (i = 0; i < rdev->wiphy.n_cipher_suites; i++)
204 if (params->cipher == rdev->wiphy.cipher_suites[i])
205 break;
206 if (i == rdev->wiphy.n_cipher_suites)
207 return -EINVAL;
208
200 return 0; 209 return 0;
201} 210}
202 211
@@ -523,3 +532,33 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie)
523 return NULL; 532 return NULL;
524} 533}
525EXPORT_SYMBOL(ieee80211_bss_get_ie); 534EXPORT_SYMBOL(ieee80211_bss_get_ie);
535
536void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
537{
538 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
539 struct net_device *dev = wdev->netdev;
540 int i;
541
542 if (!wdev->connect_keys)
543 return;
544
545 for (i = 0; i < 6; i++) {
546 if (!wdev->connect_keys->params[i].cipher)
547 continue;
548 if (rdev->ops->add_key(wdev->wiphy, dev, i, NULL,
549 &wdev->connect_keys->params[i]))
550 printk(KERN_ERR "%s: failed to set key %d\n",
551 dev->name, i);
552 if (wdev->connect_keys->def == i)
553 if (rdev->ops->set_default_key(wdev->wiphy, dev, i))
554 printk(KERN_ERR "%s: failed to set defkey %d\n",
555 dev->name, i);
556 if (wdev->connect_keys->defmgmt == i)
557 if (rdev->ops->set_default_mgmt_key(wdev->wiphy, dev, i))
558 printk(KERN_ERR "%s: failed to set mgtdef %d\n",
559 dev->name, i);
560 }
561
562 kfree(wdev->connect_keys);
563 wdev->connect_keys = NULL;
564}
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 5088d89a30fc..5d0176338539 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -453,15 +453,32 @@ int cfg80211_wext_giwretry(struct net_device *dev,
453} 453}
454EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); 454EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry);
455 455
456static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, 456static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
457 struct net_device *dev, const u8 *addr, 457 struct net_device *dev, const u8 *addr,
458 bool remove, bool tx_key, int idx, 458 bool remove, bool tx_key, int idx,
459 struct key_params *params) 459 struct key_params *params)
460{ 460{
461 struct wireless_dev *wdev = dev->ieee80211_ptr; 461 struct wireless_dev *wdev = dev->ieee80211_ptr;
462 int err; 462 int err, i;
463
464 if (!wdev->wext.keys) {
465 wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
466 GFP_KERNEL);
467 if (!wdev->wext.keys)
468 return -ENOMEM;
469 for (i = 0; i < 6; i++)
470 wdev->wext.keys->params[i].key =
471 wdev->wext.keys->data[i];
472 }
473
474 if (wdev->iftype != NL80211_IFTYPE_ADHOC &&
475 wdev->iftype != NL80211_IFTYPE_STATION)
476 return -EOPNOTSUPP;
463 477
464 if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { 478 if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
479 if (!wdev->current_bss)
480 return -ENOLINK;
481
465 if (!rdev->ops->set_default_mgmt_key) 482 if (!rdev->ops->set_default_mgmt_key)
466 return -EOPNOTSUPP; 483 return -EOPNOTSUPP;
467 484
@@ -471,8 +488,14 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
471 return -EINVAL; 488 return -EINVAL;
472 489
473 if (remove) { 490 if (remove) {
474 err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); 491 err = 0;
492 if (wdev->current_bss)
493 err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
475 if (!err) { 494 if (!err) {
495 if (!addr) {
496 wdev->wext.keys->params[idx].key_len = 0;
497 wdev->wext.keys->params[idx].cipher = 0;
498 }
476 if (idx == wdev->wext.default_key) 499 if (idx == wdev->wext.default_key)
477 wdev->wext.default_key = -1; 500 wdev->wext.default_key = -1;
478 else if (idx == wdev->wext.default_mgmt_key) 501 else if (idx == wdev->wext.default_mgmt_key)
@@ -486,36 +509,64 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
486 return 0; 509 return 0;
487 510
488 return err; 511 return err;
489 } else { 512 }
490 if (addr)
491 tx_key = false;
492 513
493 if (cfg80211_validate_key_settings(params, idx, addr)) 514 if (addr)
494 return -EINVAL; 515 tx_key = false;
495 516
517 if (cfg80211_validate_key_settings(rdev, params, idx, addr))
518 return -EINVAL;
519
520 err = 0;
521 if (wdev->current_bss)
496 err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params); 522 err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params);
497 if (err) 523 if (err)
498 return err; 524 return err;
525
526 if (!addr) {
527 wdev->wext.keys->params[idx] = *params;
528 memcpy(wdev->wext.keys->data[idx],
529 params->key, params->key_len);
530 wdev->wext.keys->params[idx].key =
531 wdev->wext.keys->data[idx];
532 }
499 533
500 if (tx_key || (!addr && wdev->wext.default_key == -1)) { 534 if (params->cipher != WLAN_CIPHER_SUITE_AES_CMAC &&
535 (tx_key || (!addr && wdev->wext.default_key == -1))) {
536 if (wdev->current_bss)
501 err = rdev->ops->set_default_key(&rdev->wiphy, 537 err = rdev->ops->set_default_key(&rdev->wiphy,
502 dev, idx); 538 dev, idx);
503 if (!err) 539 if (!err)
504 wdev->wext.default_key = idx; 540 wdev->wext.default_key = idx;
505 return err; 541 return err;
506 } 542 }
507 543
508 if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC && 544 if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
509 (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) { 545 (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
546 if (wdev->current_bss)
510 err = rdev->ops->set_default_mgmt_key(&rdev->wiphy, 547 err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
511 dev, idx); 548 dev, idx);
512 if (!err) 549 if (!err)
513 wdev->wext.default_mgmt_key = idx; 550 wdev->wext.default_mgmt_key = idx;
514 return err; 551 return err;
515 }
516
517 return 0;
518 } 552 }
553
554 return 0;
555}
556
557static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
558 struct net_device *dev, const u8 *addr,
559 bool remove, bool tx_key, int idx,
560 struct key_params *params)
561{
562 int err;
563
564 wdev_lock(dev->ieee80211_ptr);
565 err = __cfg80211_set_encryption(rdev, dev, addr, remove,
566 tx_key, idx, params);
567 wdev_unlock(dev->ieee80211_ptr);
568
569 return err;
519} 570}
520 571
521int cfg80211_wext_siwencode(struct net_device *dev, 572int cfg80211_wext_siwencode(struct net_device *dev,
@@ -528,6 +579,10 @@ int cfg80211_wext_siwencode(struct net_device *dev,
528 bool remove = false; 579 bool remove = false;
529 struct key_params params; 580 struct key_params params;
530 581
582 if (wdev->iftype != NL80211_IFTYPE_STATION &&
583 wdev->iftype != NL80211_IFTYPE_ADHOC)
584 return -EOPNOTSUPP;
585
531 /* no use -- only MFP (set_default_mgmt_key) is optional */ 586 /* no use -- only MFP (set_default_mgmt_key) is optional */
532 if (!rdev->ops->del_key || 587 if (!rdev->ops->del_key ||
533 !rdev->ops->add_key || 588 !rdev->ops->add_key ||
@@ -548,9 +603,14 @@ int cfg80211_wext_siwencode(struct net_device *dev,
548 remove = true; 603 remove = true;
549 else if (erq->length == 0) { 604 else if (erq->length == 0) {
550 /* No key data - just set the default TX key index */ 605 /* No key data - just set the default TX key index */
551 err = rdev->ops->set_default_key(&rdev->wiphy, dev, idx); 606 err = 0;
607 wdev_lock(wdev);
608 if (wdev->current_bss)
609 err = rdev->ops->set_default_key(&rdev->wiphy,
610 dev, idx);
552 if (!err) 611 if (!err)
553 wdev->wext.default_key = idx; 612 wdev->wext.default_key = idx;
613 wdev_unlock(wdev);
554 return err; 614 return err;
555 } 615 }
556 616
@@ -583,6 +643,10 @@ int cfg80211_wext_siwencodeext(struct net_device *dev,
583 struct key_params params; 643 struct key_params params;
584 u32 cipher; 644 u32 cipher;
585 645
646 if (wdev->iftype != NL80211_IFTYPE_STATION &&
647 wdev->iftype != NL80211_IFTYPE_ADHOC)
648 return -EOPNOTSUPP;
649
586 /* no use -- only MFP (set_default_mgmt_key) is optional */ 650 /* no use -- only MFP (set_default_mgmt_key) is optional */
587 if (!rdev->ops->del_key || 651 if (!rdev->ops->del_key ||
588 !rdev->ops->add_key || 652 !rdev->ops->add_key ||
@@ -656,37 +720,15 @@ int cfg80211_wext_siwencodeext(struct net_device *dev,
656} 720}
657EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext); 721EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext);
658 722
659struct giwencode_cookie {
660 size_t buflen;
661 char *keybuf;
662};
663
664static void giwencode_get_key_cb(void *cookie, struct key_params *params)
665{
666 struct giwencode_cookie *data = cookie;
667
668 if (!params->key) {
669 data->buflen = 0;
670 return;
671 }
672
673 data->buflen = min_t(size_t, data->buflen, params->key_len);
674 memcpy(data->keybuf, params->key, data->buflen);
675}
676
677int cfg80211_wext_giwencode(struct net_device *dev, 723int cfg80211_wext_giwencode(struct net_device *dev,
678 struct iw_request_info *info, 724 struct iw_request_info *info,
679 struct iw_point *erq, char *keybuf) 725 struct iw_point *erq, char *keybuf)
680{ 726{
681 struct wireless_dev *wdev = dev->ieee80211_ptr; 727 struct wireless_dev *wdev = dev->ieee80211_ptr;
682 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 728 int idx;
683 int idx, err;
684 struct giwencode_cookie data = {
685 .keybuf = keybuf,
686 .buflen = erq->length,
687 };
688 729
689 if (!rdev->ops->get_key) 730 if (wdev->iftype != NL80211_IFTYPE_STATION &&
731 wdev->iftype != NL80211_IFTYPE_ADHOC)
690 return -EOPNOTSUPP; 732 return -EOPNOTSUPP;
691 733
692 idx = erq->flags & IW_ENCODE_INDEX; 734 idx = erq->flags & IW_ENCODE_INDEX;
@@ -701,21 +743,18 @@ int cfg80211_wext_giwencode(struct net_device *dev,
701 743
702 erq->flags = idx + 1; 744 erq->flags = idx + 1;
703 745
704 err = rdev->ops->get_key(&rdev->wiphy, dev, idx, NULL, &data, 746 if (!wdev->wext.keys || !wdev->wext.keys->params[idx].cipher) {
705 giwencode_get_key_cb);
706 if (!err) {
707 erq->length = data.buflen;
708 erq->flags |= IW_ENCODE_ENABLED;
709 return 0;
710 }
711
712 if (err == -ENOENT) {
713 erq->flags |= IW_ENCODE_DISABLED; 747 erq->flags |= IW_ENCODE_DISABLED;
714 erq->length = 0; 748 erq->length = 0;
715 return 0; 749 return 0;
716 } 750 }
717 751
718 return err; 752 erq->length = min_t(size_t, erq->length,
753 wdev->wext.keys->params[idx].key_len);
754 memcpy(keybuf, wdev->wext.keys->params[idx].key, erq->length);
755 erq->flags |= IW_ENCODE_ENABLED;
756
757 return 0;
719} 758}
720EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode); 759EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode);
721 760
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index 6f75aaa7f795..c33ea9a5de78 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -10,10 +10,11 @@
10#include <net/cfg80211.h> 10#include <net/cfg80211.h>
11#include "nl80211.h" 11#include "nl80211.h"
12 12
13static int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, 13int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
14 struct wireless_dev *wdev) 14 struct wireless_dev *wdev)
15{ 15{
16 int err; 16 struct cfg80211_cached_keys *ck = NULL;
17 int err, i;
17 18
18 ASSERT_RDEV_LOCK(rdev); 19 ASSERT_RDEV_LOCK(rdev);
19 ASSERT_WDEV_LOCK(wdev); 20 ASSERT_WDEV_LOCK(wdev);
@@ -25,10 +26,25 @@ static int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
25 wdev->wext.connect.ie_len = wdev->wext.ie_len; 26 wdev->wext.connect.ie_len = wdev->wext.ie_len;
26 wdev->wext.connect.privacy = wdev->wext.default_key != -1; 27 wdev->wext.connect.privacy = wdev->wext.default_key != -1;
27 28
28 err = 0; 29 if (wdev->wext.keys) {
29 if (wdev->wext.connect.ssid_len != 0) 30 wdev->wext.keys->def = wdev->wext.default_key;
30 err = __cfg80211_connect(rdev, wdev->netdev, 31 wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;
31 &wdev->wext.connect); 32 }
33
34 if (!wdev->wext.connect.ssid_len)
35 return 0;
36
37 if (wdev->wext.keys) {
38 ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL);
39 if (!ck)
40 return -ENOMEM;
41 for (i = 0; i < 6; i++)
42 ck->params[i].key = ck->data[i];
43 }
44 err = __cfg80211_connect(rdev, wdev->netdev,
45 &wdev->wext.connect, ck);
46 if (err)
47 kfree(ck);
32 48
33 return err; 49 return err;
34} 50}