aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 5331662489f..40c36d5d737 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)