aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-12-09 13:49:02 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-12-13 15:23:29 -0500
commitf7e0104c1a4e77cc4f23d5969b0677bdc4f62c63 (patch)
tree6d1622ec2f6152b611867df1b7a0269471655b53 /net
parentdbd2fd656f2060abfd3a16257f8b51ec60f6d2ed (diff)
mac80211: support separate default keys
Add support for split default keys (unicast and multicast) in mac80211. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c2
-rw-r--r--net/mac80211/debugfs_key.c37
-rw-r--r--net/mac80211/debugfs_key.h8
-rw-r--r--net/mac80211/ieee80211_i.h5
-rw-r--r--net/mac80211/key.c45
-rw-r--r--net/mac80211/key.h3
-rw-r--r--net/mac80211/main.c3
-rw-r--r--net/mac80211/tx.c6
8 files changed, 62 insertions, 47 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 12f7dc048d34..ea06f92801e9 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -300,7 +300,7 @@ static int ieee80211_config_default_key(struct wiphy *wiphy,
300{ 300{
301 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 301 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
302 302
303 ieee80211_set_default_key(sdata, key_idx); 303 ieee80211_set_default_key(sdata, key_idx, uni, multi);
304 304
305 return 0; 305 return 0;
306} 306}
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index 5822a6ce7671..f7ef3477c24a 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -274,7 +274,8 @@ void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
274 debugfs_remove_recursive(key->debugfs.dir); 274 debugfs_remove_recursive(key->debugfs.dir);
275 key->debugfs.dir = NULL; 275 key->debugfs.dir = NULL;
276} 276}
277void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) 277
278void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
278{ 279{
279 char buf[50]; 280 char buf[50];
280 struct ieee80211_key *key; 281 struct ieee80211_key *key;
@@ -282,25 +283,29 @@ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
282 if (!sdata->debugfs.dir) 283 if (!sdata->debugfs.dir)
283 return; 284 return;
284 285
285 /* this is running under the key lock */ 286 lockdep_assert_held(&sdata->local->key_mtx);
286 287
287 key = sdata->default_key; 288 if (sdata->default_unicast_key) {
288 if (key) { 289 key = sdata->default_unicast_key;
289 sprintf(buf, "../keys/%d", key->debugfs.cnt); 290 sprintf(buf, "../keys/%d", key->debugfs.cnt);
290 sdata->debugfs.default_key = 291 sdata->debugfs.default_unicast_key =
291 debugfs_create_symlink("default_key", 292 debugfs_create_symlink("default_unicast_key",
292 sdata->debugfs.dir, buf); 293 sdata->debugfs.dir, buf);
293 } else 294 } else {
294 ieee80211_debugfs_key_remove_default(sdata); 295 debugfs_remove(sdata->debugfs.default_unicast_key);
295} 296 sdata->debugfs.default_unicast_key = NULL;
296 297 }
297void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata)
298{
299 if (!sdata)
300 return;
301 298
302 debugfs_remove(sdata->debugfs.default_key); 299 if (sdata->default_multicast_key) {
303 sdata->debugfs.default_key = NULL; 300 key = sdata->default_multicast_key;
301 sprintf(buf, "../keys/%d", key->debugfs.cnt);
302 sdata->debugfs.default_multicast_key =
303 debugfs_create_symlink("default_multicast_key",
304 sdata->debugfs.dir, buf);
305 } else {
306 debugfs_remove(sdata->debugfs.default_multicast_key);
307 sdata->debugfs.default_multicast_key = NULL;
308 }
304} 309}
305 310
306void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) 311void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/debugfs_key.h b/net/mac80211/debugfs_key.h
index 54717b4e1371..32adc77e9c77 100644
--- a/net/mac80211/debugfs_key.h
+++ b/net/mac80211/debugfs_key.h
@@ -4,8 +4,7 @@
4#ifdef CONFIG_MAC80211_DEBUGFS 4#ifdef CONFIG_MAC80211_DEBUGFS
5void ieee80211_debugfs_key_add(struct ieee80211_key *key); 5void ieee80211_debugfs_key_add(struct ieee80211_key *key);
6void ieee80211_debugfs_key_remove(struct ieee80211_key *key); 6void ieee80211_debugfs_key_remove(struct ieee80211_key *key);
7void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata); 7void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata);
8void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata);
9void ieee80211_debugfs_key_add_mgmt_default( 8void ieee80211_debugfs_key_add_mgmt_default(
10 struct ieee80211_sub_if_data *sdata); 9 struct ieee80211_sub_if_data *sdata);
11void ieee80211_debugfs_key_remove_mgmt_default( 10void ieee80211_debugfs_key_remove_mgmt_default(
@@ -17,10 +16,7 @@ static inline void ieee80211_debugfs_key_add(struct ieee80211_key *key)
17{} 16{}
18static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key) 17static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
19{} 18{}
20static inline void ieee80211_debugfs_key_add_default( 19static inline void ieee80211_debugfs_key_update_default(
21 struct ieee80211_sub_if_data *sdata)
22{}
23static inline void ieee80211_debugfs_key_remove_default(
24 struct ieee80211_sub_if_data *sdata) 20 struct ieee80211_sub_if_data *sdata)
25{} 21{}
26static inline void ieee80211_debugfs_key_add_mgmt_default( 22static inline void ieee80211_debugfs_key_add_mgmt_default(
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 72499fe5fc36..ce58b2a676e2 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -557,7 +557,7 @@ struct ieee80211_sub_if_data {
557 unsigned int fragment_next; 557 unsigned int fragment_next;
558 558
559 struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; 559 struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
560 struct ieee80211_key *default_key; 560 struct ieee80211_key *default_unicast_key, *default_multicast_key;
561 struct ieee80211_key *default_mgmt_key; 561 struct ieee80211_key *default_mgmt_key;
562 562
563 u16 sequence_number; 563 u16 sequence_number;
@@ -595,7 +595,8 @@ struct ieee80211_sub_if_data {
595 struct { 595 struct {
596 struct dentry *dir; 596 struct dentry *dir;
597 struct dentry *subdir_stations; 597 struct dentry *subdir_stations;
598 struct dentry *default_key; 598 struct dentry *default_unicast_key;
599 struct dentry *default_multicast_key;
599 struct dentry *default_mgmt_key; 600 struct dentry *default_mgmt_key;
600 } debugfs; 601 } debugfs;
601#endif 602#endif
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 72df1ca7299b..84cf9196820f 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -178,7 +178,7 @@ void ieee80211_key_removed(struct ieee80211_key_conf *key_conf)
178EXPORT_SYMBOL_GPL(ieee80211_key_removed); 178EXPORT_SYMBOL_GPL(ieee80211_key_removed);
179 179
180static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, 180static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
181 int idx) 181 int idx, bool uni, bool multi)
182{ 182{
183 struct ieee80211_key *key = NULL; 183 struct ieee80211_key *key = NULL;
184 184
@@ -187,18 +187,19 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
187 if (idx >= 0 && idx < NUM_DEFAULT_KEYS) 187 if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
188 key = sdata->keys[idx]; 188 key = sdata->keys[idx];
189 189
190 rcu_assign_pointer(sdata->default_key, key); 190 if (uni)
191 rcu_assign_pointer(sdata->default_unicast_key, key);
192 if (multi)
193 rcu_assign_pointer(sdata->default_multicast_key, key);
191 194
192 if (key) { 195 ieee80211_debugfs_key_update_default(sdata);
193 ieee80211_debugfs_key_remove_default(key->sdata);
194 ieee80211_debugfs_key_add_default(key->sdata);
195 }
196} 196}
197 197
198void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx) 198void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
199 bool uni, bool multi)
199{ 200{
200 mutex_lock(&sdata->local->key_mtx); 201 mutex_lock(&sdata->local->key_mtx);
201 __ieee80211_set_default_key(sdata, idx); 202 __ieee80211_set_default_key(sdata, idx, uni, multi);
202 mutex_unlock(&sdata->local->key_mtx); 203 mutex_unlock(&sdata->local->key_mtx);
203} 204}
204 205
@@ -215,10 +216,7 @@ __ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx)
215 216
216 rcu_assign_pointer(sdata->default_mgmt_key, key); 217 rcu_assign_pointer(sdata->default_mgmt_key, key);
217 218
218 if (key) { 219 ieee80211_debugfs_key_update_default(sdata);
219 ieee80211_debugfs_key_remove_mgmt_default(key->sdata);
220 ieee80211_debugfs_key_add_mgmt_default(key->sdata);
221 }
222} 220}
223 221
224void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, 222void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
@@ -236,7 +234,8 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
236 struct ieee80211_key *old, 234 struct ieee80211_key *old,
237 struct ieee80211_key *new) 235 struct ieee80211_key *new)
238{ 236{
239 int idx, defkey, defmgmtkey; 237 int idx;
238 bool defunikey, defmultikey, defmgmtkey;
240 239
241 if (new) 240 if (new)
242 list_add(&new->list, &sdata->key_list); 241 list_add(&new->list, &sdata->key_list);
@@ -257,17 +256,24 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
257 else 256 else
258 idx = new->conf.keyidx; 257 idx = new->conf.keyidx;
259 258
260 defkey = old && sdata->default_key == old; 259 defunikey = old && sdata->default_unicast_key == old;
260 defmultikey = old && sdata->default_multicast_key == old;
261 defmgmtkey = old && sdata->default_mgmt_key == old; 261 defmgmtkey = old && sdata->default_mgmt_key == old;
262 262
263 if (defkey && !new) 263 if (defunikey && !new)
264 __ieee80211_set_default_key(sdata, -1); 264 __ieee80211_set_default_key(sdata, -1, true, false);
265 if (defmultikey && !new)
266 __ieee80211_set_default_key(sdata, -1, false, true);
265 if (defmgmtkey && !new) 267 if (defmgmtkey && !new)
266 __ieee80211_set_default_mgmt_key(sdata, -1); 268 __ieee80211_set_default_mgmt_key(sdata, -1);
267 269
268 rcu_assign_pointer(sdata->keys[idx], new); 270 rcu_assign_pointer(sdata->keys[idx], new);
269 if (defkey && new) 271 if (defunikey && new)
270 __ieee80211_set_default_key(sdata, new->conf.keyidx); 272 __ieee80211_set_default_key(sdata, new->conf.keyidx,
273 true, false);
274 if (defmultikey && new)
275 __ieee80211_set_default_key(sdata, new->conf.keyidx,
276 false, true);
271 if (defmgmtkey && new) 277 if (defmgmtkey && new)
272 __ieee80211_set_default_mgmt_key(sdata, 278 __ieee80211_set_default_mgmt_key(sdata,
273 new->conf.keyidx); 279 new->conf.keyidx);
@@ -509,11 +515,12 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
509 515
510 mutex_lock(&sdata->local->key_mtx); 516 mutex_lock(&sdata->local->key_mtx);
511 517
512 ieee80211_debugfs_key_remove_default(sdata);
513 ieee80211_debugfs_key_remove_mgmt_default(sdata); 518 ieee80211_debugfs_key_remove_mgmt_default(sdata);
514 519
515 list_for_each_entry_safe(key, tmp, &sdata->key_list, list) 520 list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
516 __ieee80211_key_free(key); 521 __ieee80211_key_free(key);
517 522
523 ieee80211_debugfs_key_update_default(sdata);
524
518 mutex_unlock(&sdata->local->key_mtx); 525 mutex_unlock(&sdata->local->key_mtx);
519} 526}
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 0db1c0f5f697..8106aa1b7466 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -138,7 +138,8 @@ int __must_check ieee80211_key_link(struct ieee80211_key *key,
138 struct sta_info *sta); 138 struct sta_info *sta);
139void ieee80211_key_free(struct ieee80211_local *local, 139void ieee80211_key_free(struct ieee80211_local *local,
140 struct ieee80211_key *key); 140 struct ieee80211_key *key);
141void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx); 141void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
142 bool uni, bool multi);
142void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, 143void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
143 int idx); 144 int idx);
144void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); 145void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 973fee9f7d69..ae656b6e3bc2 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -519,7 +519,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
519 519
520 wiphy->flags |= WIPHY_FLAG_NETNS_OK | 520 wiphy->flags |= WIPHY_FLAG_NETNS_OK |
521 WIPHY_FLAG_4ADDR_AP | 521 WIPHY_FLAG_4ADDR_AP |
522 WIPHY_FLAG_4ADDR_STATION; 522 WIPHY_FLAG_4ADDR_STATION |
523 WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS;
523 wiphy->privid = mac80211_wiphy_privid; 524 wiphy->privid = mac80211_wiphy_privid;
524 525
525 wiphy->bss_priv_size = sizeof(struct ieee80211_bss); 526 wiphy->bss_priv_size = sizeof(struct ieee80211_bss);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 0ee56bb0ea7e..157bde993ef5 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -539,7 +539,11 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
539 ieee80211_is_robust_mgmt_frame(hdr) && 539 ieee80211_is_robust_mgmt_frame(hdr) &&
540 (key = rcu_dereference(tx->sdata->default_mgmt_key))) 540 (key = rcu_dereference(tx->sdata->default_mgmt_key)))
541 tx->key = key; 541 tx->key = key;
542 else if ((key = rcu_dereference(tx->sdata->default_key))) 542 else if (is_multicast_ether_addr(hdr->addr1) &&
543 (key = rcu_dereference(tx->sdata->default_multicast_key)))
544 tx->key = key;
545 else if (!is_multicast_ether_addr(hdr->addr1) &&
546 (key = rcu_dereference(tx->sdata->default_unicast_key)))
543 tx->key = key; 547 tx->key = key;
544 else if (tx->sdata->drop_unencrypted && 548 else if (tx->sdata->drop_unencrypted &&
545 (tx->skb->protocol != tx->sdata->control_port_protocol) && 549 (tx->skb->protocol != tx->sdata->control_port_protocol) &&