diff options
author | Johannes Berg <johannes.berg@intel.com> | 2022-07-21 20:54:20 +0300 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2022-07-22 15:28:39 +0300 |
commit | 1773af9d6a3f1f2f67e111196fa8fb9106a7c20d (patch) | |
tree | 597d232250bd755e9e5910c3ade4b68f36102026 /net/mac80211/iface.c | |
parent | 56057da4569bd716771cf4cfd031ce9876ef2516 (diff) | |
download | linux-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/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 38 |
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)); |