forked from mirrors/linux
		
	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>
This commit is contained in:
		
							parent
							
								
									dbd2fd656f
								
							
						
					
					
						commit
						f7e0104c1a
					
				
					 8 changed files with 62 additions and 47 deletions
				
			
		| 
						 | 
				
			
			@ -300,7 +300,7 @@ static int ieee80211_config_default_key(struct wiphy *wiphy,
 | 
			
		|||
{
 | 
			
		||||
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 | 
			
		||||
 | 
			
		||||
	ieee80211_set_default_key(sdata, key_idx);
 | 
			
		||||
	ieee80211_set_default_key(sdata, key_idx, uni, multi);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -274,7 +274,8 @@ void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
 | 
			
		|||
	debugfs_remove_recursive(key->debugfs.dir);
 | 
			
		||||
	key->debugfs.dir = NULL;
 | 
			
		||||
}
 | 
			
		||||
void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
 | 
			
		||||
 | 
			
		||||
void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
 | 
			
		||||
{
 | 
			
		||||
	char buf[50];
 | 
			
		||||
	struct ieee80211_key *key;
 | 
			
		||||
| 
						 | 
				
			
			@ -282,25 +283,29 @@ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
 | 
			
		|||
	if (!sdata->debugfs.dir)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* this is running under the key lock */
 | 
			
		||||
	lockdep_assert_held(&sdata->local->key_mtx);
 | 
			
		||||
 | 
			
		||||
	key = sdata->default_key;
 | 
			
		||||
	if (key) {
 | 
			
		||||
	if (sdata->default_unicast_key) {
 | 
			
		||||
		key = sdata->default_unicast_key;
 | 
			
		||||
		sprintf(buf, "../keys/%d", key->debugfs.cnt);
 | 
			
		||||
		sdata->debugfs.default_key =
 | 
			
		||||
			debugfs_create_symlink("default_key",
 | 
			
		||||
		sdata->debugfs.default_unicast_key =
 | 
			
		||||
			debugfs_create_symlink("default_unicast_key",
 | 
			
		||||
					       sdata->debugfs.dir, buf);
 | 
			
		||||
	} else
 | 
			
		||||
		ieee80211_debugfs_key_remove_default(sdata);
 | 
			
		||||
}
 | 
			
		||||
	} else {
 | 
			
		||||
		debugfs_remove(sdata->debugfs.default_unicast_key);
 | 
			
		||||
		sdata->debugfs.default_unicast_key = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata)
 | 
			
		||||
{
 | 
			
		||||
	if (!sdata)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	debugfs_remove(sdata->debugfs.default_key);
 | 
			
		||||
	sdata->debugfs.default_key = NULL;
 | 
			
		||||
	if (sdata->default_multicast_key) {
 | 
			
		||||
		key = sdata->default_multicast_key;
 | 
			
		||||
		sprintf(buf, "../keys/%d", key->debugfs.cnt);
 | 
			
		||||
		sdata->debugfs.default_multicast_key =
 | 
			
		||||
			debugfs_create_symlink("default_multicast_key",
 | 
			
		||||
					       sdata->debugfs.dir, buf);
 | 
			
		||||
	} else {
 | 
			
		||||
		debugfs_remove(sdata->debugfs.default_multicast_key);
 | 
			
		||||
		sdata->debugfs.default_multicast_key = NULL;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,8 +4,7 @@
 | 
			
		|||
#ifdef CONFIG_MAC80211_DEBUGFS
 | 
			
		||||
void ieee80211_debugfs_key_add(struct ieee80211_key *key);
 | 
			
		||||
void ieee80211_debugfs_key_remove(struct ieee80211_key *key);
 | 
			
		||||
void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata);
 | 
			
		||||
void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata);
 | 
			
		||||
void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata);
 | 
			
		||||
void ieee80211_debugfs_key_add_mgmt_default(
 | 
			
		||||
	struct ieee80211_sub_if_data *sdata);
 | 
			
		||||
void ieee80211_debugfs_key_remove_mgmt_default(
 | 
			
		||||
| 
						 | 
				
			
			@ -17,10 +16,7 @@ static inline void ieee80211_debugfs_key_add(struct ieee80211_key *key)
 | 
			
		|||
{}
 | 
			
		||||
static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
 | 
			
		||||
{}
 | 
			
		||||
static inline void ieee80211_debugfs_key_add_default(
 | 
			
		||||
	struct ieee80211_sub_if_data *sdata)
 | 
			
		||||
{}
 | 
			
		||||
static inline void ieee80211_debugfs_key_remove_default(
 | 
			
		||||
static inline void ieee80211_debugfs_key_update_default(
 | 
			
		||||
	struct ieee80211_sub_if_data *sdata)
 | 
			
		||||
{}
 | 
			
		||||
static inline void ieee80211_debugfs_key_add_mgmt_default(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -557,7 +557,7 @@ struct ieee80211_sub_if_data {
 | 
			
		|||
	unsigned int fragment_next;
 | 
			
		||||
 | 
			
		||||
	struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
 | 
			
		||||
	struct ieee80211_key *default_key;
 | 
			
		||||
	struct ieee80211_key *default_unicast_key, *default_multicast_key;
 | 
			
		||||
	struct ieee80211_key *default_mgmt_key;
 | 
			
		||||
 | 
			
		||||
	u16 sequence_number;
 | 
			
		||||
| 
						 | 
				
			
			@ -595,7 +595,8 @@ struct ieee80211_sub_if_data {
 | 
			
		|||
	struct {
 | 
			
		||||
		struct dentry *dir;
 | 
			
		||||
		struct dentry *subdir_stations;
 | 
			
		||||
		struct dentry *default_key;
 | 
			
		||||
		struct dentry *default_unicast_key;
 | 
			
		||||
		struct dentry *default_multicast_key;
 | 
			
		||||
		struct dentry *default_mgmt_key;
 | 
			
		||||
	} debugfs;
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -178,7 +178,7 @@ void ieee80211_key_removed(struct ieee80211_key_conf *key_conf)
 | 
			
		|||
EXPORT_SYMBOL_GPL(ieee80211_key_removed);
 | 
			
		||||
 | 
			
		||||
static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
 | 
			
		||||
					int idx)
 | 
			
		||||
					int idx, bool uni, bool multi)
 | 
			
		||||
{
 | 
			
		||||
	struct ieee80211_key *key = NULL;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -187,18 +187,19 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
 | 
			
		|||
	if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
 | 
			
		||||
		key = sdata->keys[idx];
 | 
			
		||||
 | 
			
		||||
	rcu_assign_pointer(sdata->default_key, key);
 | 
			
		||||
	if (uni)
 | 
			
		||||
		rcu_assign_pointer(sdata->default_unicast_key, key);
 | 
			
		||||
	if (multi)
 | 
			
		||||
		rcu_assign_pointer(sdata->default_multicast_key, key);
 | 
			
		||||
 | 
			
		||||
	if (key) {
 | 
			
		||||
		ieee80211_debugfs_key_remove_default(key->sdata);
 | 
			
		||||
		ieee80211_debugfs_key_add_default(key->sdata);
 | 
			
		||||
	}
 | 
			
		||||
	ieee80211_debugfs_key_update_default(sdata);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
 | 
			
		||||
void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
 | 
			
		||||
			       bool uni, bool multi)
 | 
			
		||||
{
 | 
			
		||||
	mutex_lock(&sdata->local->key_mtx);
 | 
			
		||||
	__ieee80211_set_default_key(sdata, idx);
 | 
			
		||||
	__ieee80211_set_default_key(sdata, idx, uni, multi);
 | 
			
		||||
	mutex_unlock(&sdata->local->key_mtx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -215,10 +216,7 @@ __ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx)
 | 
			
		|||
 | 
			
		||||
	rcu_assign_pointer(sdata->default_mgmt_key, key);
 | 
			
		||||
 | 
			
		||||
	if (key) {
 | 
			
		||||
		ieee80211_debugfs_key_remove_mgmt_default(key->sdata);
 | 
			
		||||
		ieee80211_debugfs_key_add_mgmt_default(key->sdata);
 | 
			
		||||
	}
 | 
			
		||||
	ieee80211_debugfs_key_update_default(sdata);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void 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,
 | 
			
		|||
				    struct ieee80211_key *old,
 | 
			
		||||
				    struct ieee80211_key *new)
 | 
			
		||||
{
 | 
			
		||||
	int idx, defkey, defmgmtkey;
 | 
			
		||||
	int idx;
 | 
			
		||||
	bool defunikey, defmultikey, defmgmtkey;
 | 
			
		||||
 | 
			
		||||
	if (new)
 | 
			
		||||
		list_add(&new->list, &sdata->key_list);
 | 
			
		||||
| 
						 | 
				
			
			@ -257,17 +256,24 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
 | 
			
		|||
		else
 | 
			
		||||
			idx = new->conf.keyidx;
 | 
			
		||||
 | 
			
		||||
		defkey = old && sdata->default_key == old;
 | 
			
		||||
		defunikey = old && sdata->default_unicast_key == old;
 | 
			
		||||
		defmultikey = old && sdata->default_multicast_key == old;
 | 
			
		||||
		defmgmtkey = old && sdata->default_mgmt_key == old;
 | 
			
		||||
 | 
			
		||||
		if (defkey && !new)
 | 
			
		||||
			__ieee80211_set_default_key(sdata, -1);
 | 
			
		||||
		if (defunikey && !new)
 | 
			
		||||
			__ieee80211_set_default_key(sdata, -1, true, false);
 | 
			
		||||
		if (defmultikey && !new)
 | 
			
		||||
			__ieee80211_set_default_key(sdata, -1, false, true);
 | 
			
		||||
		if (defmgmtkey && !new)
 | 
			
		||||
			__ieee80211_set_default_mgmt_key(sdata, -1);
 | 
			
		||||
 | 
			
		||||
		rcu_assign_pointer(sdata->keys[idx], new);
 | 
			
		||||
		if (defkey && new)
 | 
			
		||||
			__ieee80211_set_default_key(sdata, new->conf.keyidx);
 | 
			
		||||
		if (defunikey && new)
 | 
			
		||||
			__ieee80211_set_default_key(sdata, new->conf.keyidx,
 | 
			
		||||
						    true, false);
 | 
			
		||||
		if (defmultikey && new)
 | 
			
		||||
			__ieee80211_set_default_key(sdata, new->conf.keyidx,
 | 
			
		||||
						    false, true);
 | 
			
		||||
		if (defmgmtkey && new)
 | 
			
		||||
			__ieee80211_set_default_mgmt_key(sdata,
 | 
			
		||||
							 new->conf.keyidx);
 | 
			
		||||
| 
						 | 
				
			
			@ -509,11 +515,12 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
 | 
			
		|||
 | 
			
		||||
	mutex_lock(&sdata->local->key_mtx);
 | 
			
		||||
 | 
			
		||||
	ieee80211_debugfs_key_remove_default(sdata);
 | 
			
		||||
	ieee80211_debugfs_key_remove_mgmt_default(sdata);
 | 
			
		||||
 | 
			
		||||
	list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
 | 
			
		||||
		__ieee80211_key_free(key);
 | 
			
		||||
 | 
			
		||||
	ieee80211_debugfs_key_update_default(sdata);
 | 
			
		||||
 | 
			
		||||
	mutex_unlock(&sdata->local->key_mtx);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -138,7 +138,8 @@ int __must_check ieee80211_key_link(struct ieee80211_key *key,
 | 
			
		|||
				    struct sta_info *sta);
 | 
			
		||||
void ieee80211_key_free(struct ieee80211_local *local,
 | 
			
		||||
			struct ieee80211_key *key);
 | 
			
		||||
void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx);
 | 
			
		||||
void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
 | 
			
		||||
			       bool uni, bool multi);
 | 
			
		||||
void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
 | 
			
		||||
				    int idx);
 | 
			
		||||
void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -519,7 +519,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
 | 
			
		|||
 | 
			
		||||
	wiphy->flags |= WIPHY_FLAG_NETNS_OK |
 | 
			
		||||
			WIPHY_FLAG_4ADDR_AP |
 | 
			
		||||
			WIPHY_FLAG_4ADDR_STATION;
 | 
			
		||||
			WIPHY_FLAG_4ADDR_STATION |
 | 
			
		||||
			WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS;
 | 
			
		||||
	wiphy->privid = mac80211_wiphy_privid;
 | 
			
		||||
 | 
			
		||||
	wiphy->bss_priv_size = sizeof(struct ieee80211_bss);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -539,7 +539,11 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
 | 
			
		|||
		 ieee80211_is_robust_mgmt_frame(hdr) &&
 | 
			
		||||
		 (key = rcu_dereference(tx->sdata->default_mgmt_key)))
 | 
			
		||||
		tx->key = key;
 | 
			
		||||
	else if ((key = rcu_dereference(tx->sdata->default_key)))
 | 
			
		||||
	else if (is_multicast_ether_addr(hdr->addr1) &&
 | 
			
		||||
		 (key = rcu_dereference(tx->sdata->default_multicast_key)))
 | 
			
		||||
		tx->key = key;
 | 
			
		||||
	else if (!is_multicast_ether_addr(hdr->addr1) &&
 | 
			
		||||
		 (key = rcu_dereference(tx->sdata->default_unicast_key)))
 | 
			
		||||
		tx->key = key;
 | 
			
		||||
	else if (tx->sdata->drop_unencrypted &&
 | 
			
		||||
		 (tx->skb->protocol != tx->sdata->control_port_protocol) &&
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue