Commit ccdde7c7 authored by Johannes Berg's avatar Johannes Berg
Browse files

wifi: mac80211: properly implement MLO key handling



Implement key installation and lookup (on TX and RX)
for MLO, so we can use multiple GTKs/IGTKs/BIGTKs.

Co-authored-by: default avatarIlan Peer <ilan.peer@intel.com>
Signed-off-by: default avatarIlan Peer <ilan.peer@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent e7a7b84e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1975,6 +1975,7 @@ enum ieee80211_key_flags {
 * 	- Temporal Authenticator Rx MIC Key (64 bits)
 * @icv_len: The ICV length for this key type
 * @iv_len: The IV length for this key type
 * @link_id: the link ID for MLO, or -1 for non-MLO or pairwise keys
 */
struct ieee80211_key_conf {
	atomic64_t tx_pn;
@@ -1984,6 +1985,7 @@ struct ieee80211_key_conf {
	u8 hw_key_idx;
	s8 keyidx;
	u16 flags;
	s8 link_id;
	u8 keylen;
	u8 key[];
};
+62 −13
Original line number Diff line number Diff line
@@ -24,12 +24,18 @@
#include "wme.h"

static struct ieee80211_link_data *
ieee80211_link_or_deflink(struct ieee80211_sub_if_data *sdata, int link_id)
ieee80211_link_or_deflink(struct ieee80211_sub_if_data *sdata, int link_id,
			  bool require_valid)
{
	struct ieee80211_link_data *link;

	if (link_id < 0) {
		if (sdata->vif.valid_links)
		/*
		 * For keys, if sdata is not an MLD, we might not use
		 * the return value at all (if it's not a pairwise key),
		 * so in that case (require_valid==false) don't error.
		 */
		if (require_valid && sdata->vif.valid_links)
			return ERR_PTR(-EINVAL);

		return &sdata->deflink;
@@ -456,6 +462,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
			     const u8 *mac_addr, struct key_params *params)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct ieee80211_link_data *link =
		ieee80211_link_or_deflink(sdata, link_id, false);
	struct ieee80211_local *local = sdata->local;
	struct sta_info *sta = NULL;
	struct ieee80211_key *key;
@@ -464,6 +472,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
	if (!ieee80211_sdata_running(sdata))
		return -ENETDOWN;

	if (IS_ERR(link))
		return PTR_ERR(link);

	if (pairwise && params->mode == NL80211_KEY_SET_TX)
		return ieee80211_set_tx(sdata, mac_addr, key_idx);

@@ -472,6 +483,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
	case WLAN_CIPHER_SUITE_WEP40:
	case WLAN_CIPHER_SUITE_TKIP:
	case WLAN_CIPHER_SUITE_WEP104:
		if (link_id >= 0)
			return -EINVAL;
		if (WARN_ON_ONCE(fips_enabled))
			return -EINVAL;
		break;
@@ -484,6 +497,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
	if (IS_ERR(key))
		return PTR_ERR(key);

	key->conf.link_id = link_id;

	if (pairwise)
		key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE;

@@ -545,7 +560,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
		break;
	}

	err = ieee80211_key_link(key, sdata, sta);
	err = ieee80211_key_link(key, link, sta);

 out_unlock:
	mutex_unlock(&local->sta_mtx);
@@ -554,18 +569,37 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
}

static struct ieee80211_key *
ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata,
ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata, int link_id,
		     u8 key_idx, bool pairwise, const u8 *mac_addr)
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_link_data *link = &sdata->deflink;
	struct ieee80211_key *key;
	struct sta_info *sta;

	if (link_id >= 0) {
		link = rcu_dereference_check(sdata->link[link_id],
					     lockdep_is_held(&sdata->wdev.mtx));
		if (!link)
			return NULL;
	}

	if (mac_addr) {
		struct sta_info *sta;
		struct link_sta_info *link_sta;

		sta = sta_info_get_bss(sdata, mac_addr);
		if (!sta)
			return NULL;

		if (link_id >= 0) {
			link_sta = rcu_dereference_check(sta->link[link_id],
							 lockdep_is_held(&local->sta_mtx));
			if (!link_sta)
				return NULL;
		} else {
			link_sta = &sta->deflink;
		}

		if (pairwise && key_idx < NUM_DEFAULT_KEYS)
			return rcu_dereference_check_key_mtx(local,
							     sta->ptk[key_idx]);
@@ -575,7 +609,7 @@ ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata,
			      NUM_DEFAULT_MGMT_KEYS +
			      NUM_DEFAULT_BEACON_KEYS)
			return rcu_dereference_check_key_mtx(local,
							     sta->deflink.gtk[key_idx]);
							     link_sta->gtk[key_idx]);

		return NULL;
	}
@@ -584,7 +618,7 @@ ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata,
		return rcu_dereference_check_key_mtx(local,
						     sdata->keys[key_idx]);

	key = rcu_dereference_check_key_mtx(local, sdata->deflink.gtk[key_idx]);
	key = rcu_dereference_check_key_mtx(local, link->gtk[key_idx]);
	if (key)
		return key;

@@ -607,7 +641,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
	mutex_lock(&local->sta_mtx);
	mutex_lock(&local->key_mtx);

	key = ieee80211_lookup_key(sdata, key_idx, pairwise, mac_addr);
	key = ieee80211_lookup_key(sdata, link_id, key_idx, pairwise, mac_addr);
	if (!key) {
		ret = -ENOENT;
		goto out_unlock;
@@ -643,7 +677,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,

	rcu_read_lock();

	key = ieee80211_lookup_key(sdata, key_idx, pairwise, mac_addr);
	key = ieee80211_lookup_key(sdata, link_id, key_idx, pairwise, mac_addr);
	if (!key)
		goto out;

@@ -734,8 +768,13 @@ static int ieee80211_config_default_key(struct wiphy *wiphy,
					bool multi)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct ieee80211_link_data *link =
		ieee80211_link_or_deflink(sdata, link_id, false);

	if (IS_ERR(link))
		return PTR_ERR(link);

	ieee80211_set_default_key(sdata, key_idx, uni, multi);
	ieee80211_set_default_key(link, key_idx, uni, multi);

	return 0;
}
@@ -745,8 +784,13 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
					     int link_id, u8 key_idx)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct ieee80211_link_data *link =
		ieee80211_link_or_deflink(sdata, link_id, true);

	if (IS_ERR(link))
		return PTR_ERR(link);

	ieee80211_set_default_mgmt_key(sdata, key_idx);
	ieee80211_set_default_mgmt_key(link, key_idx);

	return 0;
}
@@ -756,8 +800,13 @@ static int ieee80211_config_default_beacon_key(struct wiphy *wiphy,
					       int link_id, u8 key_idx)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct ieee80211_link_data *link =
		ieee80211_link_or_deflink(sdata, link_id, true);

	if (IS_ERR(link))
		return PTR_ERR(link);

	ieee80211_set_default_beacon_key(sdata, key_idx);
	ieee80211_set_default_beacon_key(link, key_idx);

	return 0;
}
@@ -2588,7 +2637,7 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
	struct ieee80211_local *local = wiphy_priv(wiphy);
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct ieee80211_link_data *link =
		ieee80211_link_or_deflink(sdata, params->link_id);
		ieee80211_link_or_deflink(sdata, params->link_id, true);
	struct ieee80211_tx_queue_params p;

	if (!local->ops->conf_tx)
+1 −0
Original line number Diff line number Diff line
@@ -213,6 +213,7 @@ struct ieee80211_rx_data {
	struct ieee80211_sub_if_data *sdata;
	struct ieee80211_link_data *link;
	struct sta_info *sta;
	struct link_sta_info *link_sta;
	struct ieee80211_key *key;

	unsigned int flags;
+9 −0
Original line number Diff line number Diff line
@@ -434,10 +434,19 @@ struct link_container {
static void ieee80211_free_links(struct ieee80211_sub_if_data *sdata,
				 struct link_container **links)
{
	LIST_HEAD(keys);
	unsigned int link_id;

	for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
		if (!links[link_id])
			continue;
		ieee80211_remove_link_keys(&links[link_id]->data, &keys);
	}

	synchronize_rcu();

	ieee80211_free_key_list(sdata->local, &keys);

	for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
		if (!links[link_id])
			continue;
+131 −59
Original line number Diff line number Diff line
@@ -344,9 +344,10 @@ static void ieee80211_pairwise_rekey(struct ieee80211_key *old,
	}
}

static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
static void __ieee80211_set_default_key(struct ieee80211_link_data *link,
					int idx, bool uni, bool multi)
{
	struct ieee80211_sub_if_data *sdata = link->sdata;
	struct ieee80211_key *key = NULL;

	assert_key_lock(sdata->local);
@@ -354,7 +355,7 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
	if (idx >= 0 && idx < NUM_DEFAULT_KEYS) {
		key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
		if (!key)
			key = key_mtx_dereference(sdata->local, sdata->deflink.gtk[idx]);
			key = key_mtx_dereference(sdata->local, link->gtk[idx]);
	}

	if (uni) {
@@ -365,47 +366,48 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
	}

	if (multi)
		rcu_assign_pointer(sdata->deflink.default_multicast_key, key);
		rcu_assign_pointer(link->default_multicast_key, key);

	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_link_data *link, int idx,
			       bool uni, bool multi)
{
	mutex_lock(&sdata->local->key_mtx);
	__ieee80211_set_default_key(sdata, idx, uni, multi);
	mutex_unlock(&sdata->local->key_mtx);
	mutex_lock(&link->sdata->local->key_mtx);
	__ieee80211_set_default_key(link, idx, uni, multi);
	mutex_unlock(&link->sdata->local->key_mtx);
}

static void
__ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx)
__ieee80211_set_default_mgmt_key(struct ieee80211_link_data *link, int idx)
{
	struct ieee80211_sub_if_data *sdata = link->sdata;
	struct ieee80211_key *key = NULL;

	assert_key_lock(sdata->local);

	if (idx >= NUM_DEFAULT_KEYS &&
	    idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
		key = key_mtx_dereference(sdata->local,
					  sdata->deflink.gtk[idx]);
		key = key_mtx_dereference(sdata->local, link->gtk[idx]);

	rcu_assign_pointer(sdata->deflink.default_mgmt_key, key);
	rcu_assign_pointer(link->default_mgmt_key, key);

	ieee80211_debugfs_key_update_default(sdata);
}

void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
void ieee80211_set_default_mgmt_key(struct ieee80211_link_data *link,
				    int idx)
{
	mutex_lock(&sdata->local->key_mtx);
	__ieee80211_set_default_mgmt_key(sdata, idx);
	mutex_unlock(&sdata->local->key_mtx);
	mutex_lock(&link->sdata->local->key_mtx);
	__ieee80211_set_default_mgmt_key(link, idx);
	mutex_unlock(&link->sdata->local->key_mtx);
}

static void
__ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata, int idx)
__ieee80211_set_default_beacon_key(struct ieee80211_link_data *link, int idx)
{
	struct ieee80211_sub_if_data *sdata = link->sdata;
	struct ieee80211_key *key = NULL;

	assert_key_lock(sdata->local);
@@ -413,28 +415,30 @@ __ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata, int idx)
	if (idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS &&
	    idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
	    NUM_DEFAULT_BEACON_KEYS)
		key = key_mtx_dereference(sdata->local,
					  sdata->deflink.gtk[idx]);
		key = key_mtx_dereference(sdata->local, link->gtk[idx]);

	rcu_assign_pointer(sdata->deflink.default_beacon_key, key);
	rcu_assign_pointer(link->default_beacon_key, key);

	ieee80211_debugfs_key_update_default(sdata);
}

void ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata,
void ieee80211_set_default_beacon_key(struct ieee80211_link_data *link,
				      int idx)
{
	mutex_lock(&sdata->local->key_mtx);
	__ieee80211_set_default_beacon_key(sdata, idx);
	mutex_unlock(&sdata->local->key_mtx);
	mutex_lock(&link->sdata->local->key_mtx);
	__ieee80211_set_default_beacon_key(link, idx);
	mutex_unlock(&link->sdata->local->key_mtx);
}

static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
				 struct ieee80211_link_data *link,
				 struct sta_info *sta,
				 bool pairwise,
				 struct ieee80211_key *old,
				 struct ieee80211_key *new)
{
	struct link_sta_info *link_sta = sta ? &sta->deflink : NULL;
	int link_id;
	int idx;
	int ret = 0;
	bool defunikey, defmultikey, defmgmtkey, defbeaconkey;
@@ -446,13 +450,36 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,

	if (new) {
		idx = new->conf.keyidx;
		list_add_tail_rcu(&new->list, &sdata->key_list);
		is_wep = new->conf.cipher == WLAN_CIPHER_SUITE_WEP40 ||
			 new->conf.cipher == WLAN_CIPHER_SUITE_WEP104;
		link_id = new->conf.link_id;
	} else {
		idx = old->conf.keyidx;
		is_wep = old->conf.cipher == WLAN_CIPHER_SUITE_WEP40 ||
			 old->conf.cipher == WLAN_CIPHER_SUITE_WEP104;
		link_id = old->conf.link_id;
	}

	if (WARN(old && old->conf.link_id != link_id,
		 "old link ID %d doesn't match new link ID %d\n",
		 old->conf.link_id, link_id))
		return -EINVAL;

	if (link_id >= 0) {
		if (!link) {
			link = sdata_dereference(sdata->link[link_id], sdata);
			if (!link)
				return -ENOLINK;
		}

		if (sta) {
			link_sta = rcu_dereference_protected(sta->link[link_id],
							     lockdep_is_held(&sta->local->sta_mtx));
			if (!link_sta)
				return -ENOLINK;
		}
	} else {
		link = &sdata->deflink;
	}

	if ((is_wep || pairwise) && idx >= NUM_DEFAULT_KEYS)
@@ -482,6 +509,9 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
	if (ret)
		return ret;

	if (new)
		list_add_tail_rcu(&new->list, &sdata->key_list);

	if (sta) {
		if (pairwise) {
			rcu_assign_pointer(sta->ptk[idx], new);
@@ -489,7 +519,7 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
			    !(new->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX))
				_ieee80211_set_tx_key(new, true);
		} else {
			rcu_assign_pointer(sta->deflink.gtk[idx], new);
			rcu_assign_pointer(link_sta->gtk[idx], new);
		}
		/* Only needed for transition from no key -> key.
		 * Still triggers unnecessary when using Extended Key ID
@@ -503,39 +533,39 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
						sdata->default_unicast_key);
		defmultikey = old &&
			old == key_mtx_dereference(sdata->local,
						sdata->deflink.default_multicast_key);
						   link->default_multicast_key);
		defmgmtkey = old &&
			old == key_mtx_dereference(sdata->local,
						sdata->deflink.default_mgmt_key);
						   link->default_mgmt_key);
		defbeaconkey = old &&
			old == key_mtx_dereference(sdata->local,
						   sdata->deflink.default_beacon_key);
						   link->default_beacon_key);

		if (defunikey && !new)
			__ieee80211_set_default_key(sdata, -1, true, false);
			__ieee80211_set_default_key(link, -1, true, false);
		if (defmultikey && !new)
			__ieee80211_set_default_key(sdata, -1, false, true);
			__ieee80211_set_default_key(link, -1, false, true);
		if (defmgmtkey && !new)
			__ieee80211_set_default_mgmt_key(sdata, -1);
			__ieee80211_set_default_mgmt_key(link, -1);
		if (defbeaconkey && !new)
			__ieee80211_set_default_beacon_key(sdata, -1);
			__ieee80211_set_default_beacon_key(link, -1);

		if (is_wep || pairwise)
			rcu_assign_pointer(sdata->keys[idx], new);
		else
			rcu_assign_pointer(sdata->deflink.gtk[idx], new);
			rcu_assign_pointer(link->gtk[idx], new);

		if (defunikey && new)
			__ieee80211_set_default_key(sdata, new->conf.keyidx,
			__ieee80211_set_default_key(link, new->conf.keyidx,
						    true, false);
		if (defmultikey && new)
			__ieee80211_set_default_key(sdata, new->conf.keyidx,
			__ieee80211_set_default_key(link, new->conf.keyidx,
						    false, true);
		if (defmgmtkey && new)
			__ieee80211_set_default_mgmt_key(sdata,
			__ieee80211_set_default_mgmt_key(link,
							 new->conf.keyidx);
		if (defbeaconkey && new)
			__ieee80211_set_default_beacon_key(sdata,
			__ieee80211_set_default_beacon_key(link,
							   new->conf.keyidx);
	}

@@ -569,6 +599,7 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
	key->conf.flags = 0;
	key->flags = 0;

	key->conf.link_id = -1;
	key->conf.cipher = cipher;
	key->conf.keyidx = idx;
	key->conf.keylen = key_len;
@@ -797,9 +828,10 @@ static bool ieee80211_key_identical(struct ieee80211_sub_if_data *sdata,
}

int ieee80211_key_link(struct ieee80211_key *key,
		       struct ieee80211_sub_if_data *sdata,
		       struct ieee80211_link_data *link,
		       struct sta_info *sta)
{
	struct ieee80211_sub_if_data *sdata = link->sdata;
	static atomic_t key_color = ATOMIC_INIT(0);
	struct ieee80211_key *old_key = NULL;
	int idx = key->conf.keyidx;
@@ -827,15 +859,24 @@ int ieee80211_key_link(struct ieee80211_key *key,
		    (old_key && old_key->conf.cipher != key->conf.cipher))
			goto out;
	} else if (sta) {
		old_key = key_mtx_dereference(sdata->local,
					      sta->deflink.gtk[idx]);
		struct link_sta_info *link_sta = &sta->deflink;
		int link_id = key->conf.link_id;

		if (link_id >= 0) {
			link_sta = rcu_dereference_protected(sta->link[link_id],
							     lockdep_is_held(&sta->local->sta_mtx));
			if (!link_sta)
				return -ENOLINK;
		}

		old_key = key_mtx_dereference(sdata->local, link_sta->gtk[idx]);
	} else {
		if (idx < NUM_DEFAULT_KEYS)
			old_key = key_mtx_dereference(sdata->local,
						      sdata->keys[idx]);
		if (!old_key)
			old_key = key_mtx_dereference(sdata->local,
						      sdata->deflink.gtk[idx]);
						      link->gtk[idx]);
	}

	/* Non-pairwise keys must also not switch the cipher on rekey */
@@ -866,7 +907,7 @@ int ieee80211_key_link(struct ieee80211_key *key,

	increment_tailroom_need_count(sdata);

	ret = ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
	ret = ieee80211_key_replace(sdata, link, sta, pairwise, old_key, key);

	if (!ret) {
		ieee80211_debugfs_key_add(key);
@@ -890,7 +931,7 @@ void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom)
	 * Replace key with nothingness if it was ever used.
	 */
	if (key->sdata)
		ieee80211_key_replace(key->sdata, key->sta,
		ieee80211_key_replace(key->sdata, NULL, key->sta,
				      key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
				      key, NULL);
	ieee80211_key_destroy(key, delay_tailroom);
@@ -1019,7 +1060,7 @@ static void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata,
	ieee80211_debugfs_key_remove_beacon_default(sdata);

	list_for_each_entry_safe(key, tmp, &sdata->key_list, list) {
		ieee80211_key_replace(key->sdata, key->sta,
		ieee80211_key_replace(key->sdata, NULL, key->sta,
				      key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
				      key, NULL);
		list_add_tail(&key->list, keys);
@@ -1028,6 +1069,36 @@ static void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata,
	ieee80211_debugfs_key_update_default(sdata);
}

void ieee80211_remove_link_keys(struct ieee80211_link_data *link,
				struct list_head *keys)
{
	struct ieee80211_sub_if_data *sdata = link->sdata;
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_key *key, *tmp;

	mutex_lock(&local->key_mtx);
	list_for_each_entry_safe(key, tmp, &sdata->key_list, list) {
		if (key->conf.link_id != link->link_id)
			continue;
		ieee80211_key_replace(key->sdata, link, key->sta,
				      key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
				      key, NULL);
		list_add_tail(&key->list, keys);
	}
	mutex_unlock(&local->key_mtx);
}

void ieee80211_free_key_list(struct ieee80211_local *local,
			     struct list_head *keys)
{
	struct ieee80211_key *key, *tmp;

	mutex_lock(&local->key_mtx);
	list_for_each_entry_safe(key, tmp, keys, list)
		__ieee80211_key_destroy(key, false);
	mutex_unlock(&local->key_mtx);
}

void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata,
			 bool force_synchronize)
{
@@ -1087,7 +1158,7 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local,
		key = key_mtx_dereference(local, sta->deflink.gtk[i]);
		if (!key)
			continue;
		ieee80211_key_replace(key->sdata, key->sta,
		ieee80211_key_replace(key->sdata, NULL, key->sta,
				      key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
				      key, NULL);
		__ieee80211_key_destroy(key, key->sdata->vif.type ==
@@ -1098,7 +1169,7 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local,
		key = key_mtx_dereference(local, sta->ptk[i]);
		if (!key)
			continue;
		ieee80211_key_replace(key->sdata, key->sta,
		ieee80211_key_replace(key->sdata, NULL, key->sta,
				      key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
				      key, NULL);
		__ieee80211_key_destroy(key, key->sdata->vif.type ==
@@ -1307,7 +1378,8 @@ ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
	if (sdata->u.mgd.mfp != IEEE80211_MFP_DISABLED)
		key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT;

	err = ieee80211_key_link(key, sdata, NULL);
	/* FIXME: this function needs to get a link ID */
	err = ieee80211_key_link(key, &sdata->deflink, NULL);
	if (err)
		return ERR_PTR(err);

Loading