If a driver registers an address mask we should ensure that no interface
gets an address assigned that isn't covered by the registered address
mask.
Signed-off-by: Helmut Schaa <[email protected]>
---
As far as I could see addr_mask is not used by any driver yetbut we're
going to use it in rt2x00 in a follow-up patch.
Helmut
net/mac80211/iface.c | 23 +++++++++++++++++++++++
1 files changed, 23 insertions(+), 0 deletions(-)
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index bc3e3e1..1f84dd1 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -191,12 +191,35 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
static int ieee80211_change_mac(struct net_device *dev, void *addr)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = sdata->local;
struct sockaddr *sa = addr;
int ret;
+ u64 perm, new, mask;
+ u8 *m;
if (ieee80211_sdata_running(sdata))
return -EBUSY;
+ if (!is_zero_ether_addr(local->hw.wiphy->addr_mask)) {
+ m = local->hw.wiphy->perm_addr;
+ perm = ((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);
+
+ m = local->hw.wiphy->addr_mask;
+ mask = ((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);
+
+ m = sa->sa_data;
+ new = ((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);
+
+ if ((new & ~mask) != (perm & ~mask))
+ return -EINVAL;
+ }
+
ret = eth_mac_addr(dev, sa);
if (ret == 0)
--
1.7.7
If a driver registers an address mask we should ensure that no interface
gets an address assigned that isn't covered by the registered address
mask.
Signed-off-by: Helmut Schaa <[email protected]>
---
Changes since v1:
* Don't match against perm address, just verify if all virtual interface
addresses fit within registered mask.
net/mac80211/iface.c | 39 +++++++++++++++++++++++++++++++++++++++
1 files changed, 39 insertions(+), 0 deletions(-)
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index bc3e3e1..6b116a0 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -188,6 +188,41 @@ 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)
+{
+ struct ieee80211_sub_if_data *sdata;
+ u64 new, mask, tmp;
+ u8 *m;
+
+ if (!is_zero_ether_addr(local->hw.wiphy->addr_mask)) {
+ m = addr;
+ new = ((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);
+
+ m = local->hw.wiphy->addr_mask;
+ mask = ((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);
+
+
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+ continue;
+
+ m = sdata->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);
+
+ if ((new & ~mask) != (tmp & ~mask))
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int ieee80211_change_mac(struct net_device *dev, void *addr)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -197,6 +232,10 @@ 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);
+ if (ret)
+ return ret;
+
ret = eth_mac_addr(dev, sa);
if (ret == 0)
--
1.7.7
On Tue, 2012-11-27 at 16:43 +0100, Helmut Schaa wrote:
> + if (!is_zero_ether_addr(local->hw.wiphy->addr_mask)) {
> + m = local->hw.wiphy->perm_addr;
I'm not sure I like using perm_addr here. You might actually want to use
a totally different address, but fit all of them into the mask, no?
johannes
On Wed, Nov 28, 2012 at 1:53 PM, Johannes Berg
<[email protected]> wrote:
> On Tue, 2012-11-27 at 18:23 +0100, Helmut Schaa wrote:
>> If a driver registers an address mask we should ensure that no interface
>> gets an address assigned that isn't covered by the registered address
>> mask.
>
> Applied with a few changes, please check.
Yep, looks good. Thanks for fixing up the locking!
Helmut
On Tue, Nov 27, 2012 at 5:07 PM, Johannes Berg
<[email protected]> wrote:
> On Tue, 2012-11-27 at 16:43 +0100, Helmut Schaa wrote:
>
>> + if (!is_zero_ether_addr(local->hw.wiphy->addr_mask)) {
>> + m = local->hw.wiphy->perm_addr;
>
> I'm not sure I like using perm_addr here. You might actually want to use
> a totally different address, but fit all of them into the mask, no?
Agreed, I'll respin.
Thanks,
Helmut
On Tue, 2012-11-27 at 18:23 +0100, Helmut Schaa wrote:
> If a driver registers an address mask we should ensure that no interface
> gets an address assigned that isn't covered by the registered address
> mask.
Applied with a few changes, please check.
johannes