diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-07-08 08:22:54 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-07-24 15:05:09 -0400 |
commit | fffd0934b9390f34bec45762192b7edd3b12b4b5 (patch) | |
tree | d9779803763261f5795fe39a402d79c4220a3a22 /net/wireless/ibss.c | |
parent | b9454e83cac42fcdc90bfbfba479132bd6629455 (diff) |
cfg80211: rework key operation
This reworks the key operation in cfg80211, and now only
allows, from userspace, configuring keys (via nl80211)
after the connection has been established (in managed
mode), the IBSS been joined (in IBSS mode), at any time
(in AP[_VLAN] modes) or never for all the other modes.
In order to do shared key authentication correctly, it
is now possible to give a WEP key to the AUTH command.
To configure static WEP keys, these are given to the
CONNECT or IBSS_JOIN command directly, for a userspace
SME it is assumed it will configure it properly after
the connection has been established.
Since mac80211 used to check the default key in IBSS
mode to see whether or not the network is protected,
it needs an update in that area, as well as an update
to make use of the WEP key passed to auth() for shared
key authentication.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/ibss.c')
-rw-r--r-- | net/wireless/ibss.c | 79 |
1 files changed, 66 insertions, 13 deletions
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 | ||
72 | int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | 74 | int __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 | ||
98 | int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | 106 | int 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, | |||
112 | static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) | 121 | static 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 |
175 | static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, | 197 | int 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 | ||
223 | int cfg80211_ibss_wext_siwfreq(struct net_device *dev, | 264 | int 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 */ |
271 | EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwfreq); | 316 | EXPORT_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 */ |
339 | EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwessid); | 388 | EXPORT_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 */ |
420 | EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwap); | 473 | EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwap); |