summaryrefslogtreecommitdiff
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2022-07-21 20:54:20 +0300
committerJohannes Berg <johannes.berg@intel.com>2022-07-22 15:28:39 +0300
commit1773af9d6a3f1f2f67e111196fa8fb9106a7c20d (patch)
tree597d232250bd755e9e5910c3ade4b68f36102026 /net/mac80211
parent56057da4569bd716771cf4cfd031ce9876ef2516 (diff)
downloadlinux-1773af9d6a3f1f2f67e111196fa8fb9106a7c20d.tar.xz
wifi: mac80211: verify link addresses are different
When adding multiple links, verify that they all have different addresses. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/iface.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index bf3bc43411ac..e544621ead0e 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -444,6 +444,32 @@ static void ieee80211_free_links(struct ieee80211_sub_if_data *sdata,
}
}
+static int ieee80211_check_dup_link_addrs(struct ieee80211_sub_if_data *sdata)
+{
+ unsigned int i, j;
+
+ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
+ struct ieee80211_link_data *link1;
+
+ link1 = sdata_dereference(sdata->link[i], sdata);
+ if (!link1)
+ continue;
+ for (j = i + 1; j < IEEE80211_MLD_MAX_NUM_LINKS; j++) {
+ struct ieee80211_link_data *link2;
+
+ link2 = sdata_dereference(sdata->link[j], sdata);
+ if (!link2)
+ continue;
+
+ if (ether_addr_equal(link1->conf->addr,
+ link2->conf->addr))
+ return -EALREADY;
+ }
+ }
+
+ return 0;
+}
+
static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
struct link_container **to_free,
u16 new_links)
@@ -518,10 +544,14 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
sdata->vif.valid_links = new_links;
- /* tell the driver */
- ret = drv_change_vif_links(sdata->local, sdata,
- old_links, new_links,
- old);
+ ret = ieee80211_check_dup_link_addrs(sdata);
+ if (!ret) {
+ /* tell the driver */
+ ret = drv_change_vif_links(sdata->local, sdata,
+ old_links, new_links,
+ old);
+ }
+
if (ret) {
/* restore config */
memcpy(sdata->link, old_data, sizeof(old_data));