aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/iface.c
diff options
context:
space:
mode:
authorHelmut Schaa <helmut.schaa@googlemail.com>2012-11-27 12:23:06 -0500
committerJohannes Berg <johannes.berg@intel.com>2012-11-28 07:52:43 -0500
commit478622e81c735ecd83d45ee6be3fd45d500aaa3b (patch)
tree631025a1b4b881e9ed179bc39d57f82b5cb13827 /net/mac80211/iface.c
parent0624760c96da3ffeaec8027a016475ae752d75e1 (diff)
mac80211: reject setting masked mac addresses
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. This prevents invalid configurations from reaching the device and causing problems. Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com> [change function flow to reduce indentation, fix locking] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r--net/mac80211/iface.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 5331662489f7..40c36d5d7377 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -223,6 +223,47 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
223 return 0; 223 return 0;
224} 224}
225 225
226static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr)
227{
228 struct ieee80211_sub_if_data *sdata;
229 u64 new, mask, tmp;
230 u8 *m;
231 int ret = 0;
232
233 if (is_zero_ether_addr(local->hw.wiphy->addr_mask))
234 return 0;
235
236 m = addr;
237 new = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
238 ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
239 ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
240
241 m = local->hw.wiphy->addr_mask;
242 mask = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
243 ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
244 ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
245
246
247 mutex_lock(&local->iflist_mtx);
248 list_for_each_entry(sdata, &local->interfaces, list) {
249 if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
250 continue;
251
252 m = sdata->vif.addr;
253 tmp = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
254 ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
255 ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
256
257 if ((new & ~mask) != (tmp & ~mask)) {
258 ret = -EINVAL;
259 break;
260 }
261 }
262 mutex_unlock(&local->iflist_mtx);
263
264 return ret;
265}
266
226static int ieee80211_change_mac(struct net_device *dev, void *addr) 267static int ieee80211_change_mac(struct net_device *dev, void *addr)
227{ 268{
228 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 269 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -232,6 +273,10 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)
232 if (ieee80211_sdata_running(sdata)) 273 if (ieee80211_sdata_running(sdata))
233 return -EBUSY; 274 return -EBUSY;
234 275
276 ret = ieee80211_verify_mac(sdata->local, sa->sa_data);
277 if (ret)
278 return ret;
279
235 ret = eth_mac_addr(dev, sa); 280 ret = eth_mac_addr(dev, sa);
236 281
237 if (ret == 0) 282 if (ret == 0)