summaryrefslogtreecommitdiff
path: root/net/mac80211
diff options
context:
space:
mode:
authorHelmut Schaa <helmut.schaa@googlemail.com>2013-05-27 12:43:09 +0400
committerJohannes Berg <johannes.berg@intel.com>2013-05-27 13:26:48 +0400
commitac20976dcaeea3e77e40e9aac8f3799d2a22ea2b (patch)
tree7bc556412be7f6af7abf15a500d973e48d993dc9 /net/mac80211
parentc8aa22db0112f640ac6631347f850879c621840b (diff)
downloadlinux-ac20976dcaeea3e77e40e9aac8f3799d2a22ea2b.tar.xz
mac80211: Allow single vif mac address change with addr_mask
When changing the MAC address of a single vif mac80211 will check if the new address fits into the address mask specified by the driver. This only needs to be done when using multiple BSSIDs. Hence, check the new address only against all other vifs. Also fix the MAC address assignment on new interfaces if the user changed the address of a vif such that perm_addr is not covered by addr_mask anymore. Resolves: https://bugzilla.kernel.org/show_bug.cgi?id=57371 Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com> Signed-off-by: Jakub Kicinski <kubakici@wp.pl> Reported-by: Alessandro Lannocca <alessandro.lannocca@gmail.com> Cc: Alessandro Lannocca <alessandro.lannocca@gmail.com> Cc: Bruno Randolf <br1@thinktube.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/iface.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index ceef64426a8d..98d20c0f6fed 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -159,9 +159,10 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
-static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr)
+static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr)
{
- struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_sub_if_data *iter;
u64 new, mask, tmp;
u8 *m;
int ret = 0;
@@ -181,11 +182,14 @@ static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr)
mutex_lock(&local->iflist_mtx);
- list_for_each_entry(sdata, &local->interfaces, list) {
- if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+ list_for_each_entry(iter, &local->interfaces, list) {
+ if (iter == sdata)
continue;
- m = sdata->vif.addr;
+ if (iter->vif.type == NL80211_IFTYPE_MONITOR)
+ continue;
+
+ m = iter->vif.addr;
tmp = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
@@ -209,7 +213,7 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)
if (ieee80211_sdata_running(sdata))
return -EBUSY;
- ret = ieee80211_verify_mac(sdata->local, sa->sa_data);
+ ret = ieee80211_verify_mac(sdata, sa->sa_data);
if (ret)
return ret;
@@ -1486,7 +1490,17 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
break;
}
+ /*
+ * Pick address of existing interface in case user changed
+ * MAC address manually, default to perm_addr.
+ */
m = local->hw.wiphy->perm_addr;
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+ continue;
+ m = sdata->vif.addr;
+ break;
+ }
start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);