diff options
-rw-r--r-- | net/mac80211/iface.c | 45 |
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 | ||
226 | static 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 | |||
226 | static int ieee80211_change_mac(struct net_device *dev, void *addr) | 267 | static 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) |