diff options
-rw-r--r-- | net/mac80211/main.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index f5537f90dd36..93dcdc27254b 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -187,9 +187,15 @@ static int ieee80211_open(struct net_device *dev) | |||
187 | u32 changed = 0; | 187 | u32 changed = 0; |
188 | int res; | 188 | int res; |
189 | bool need_hw_reconfig = 0; | 189 | bool need_hw_reconfig = 0; |
190 | u8 null_addr[ETH_ALEN] = {0}; | ||
190 | 191 | ||
191 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 192 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
192 | 193 | ||
194 | /* fail early if user set an invalid address */ | ||
195 | if (compare_ether_addr(dev->dev_addr, null_addr) && | ||
196 | !is_valid_ether_addr(dev->dev_addr)) | ||
197 | return -EADDRNOTAVAIL; | ||
198 | |||
193 | /* we hold the RTNL here so can safely walk the list */ | 199 | /* we hold the RTNL here so can safely walk the list */ |
194 | list_for_each_entry(nsdata, &local->interfaces, list) { | 200 | list_for_each_entry(nsdata, &local->interfaces, list) { |
195 | struct net_device *ndev = nsdata->dev; | 201 | struct net_device *ndev = nsdata->dev; |
@@ -270,6 +276,36 @@ static int ieee80211_open(struct net_device *dev) | |||
270 | ieee80211_led_radio(local, local->hw.conf.radio_enabled); | 276 | ieee80211_led_radio(local, local->hw.conf.radio_enabled); |
271 | } | 277 | } |
272 | 278 | ||
279 | /* | ||
280 | * Check all interfaces and copy the hopefully now-present | ||
281 | * MAC address to those that have the special null one. | ||
282 | */ | ||
283 | list_for_each_entry(nsdata, &local->interfaces, list) { | ||
284 | struct net_device *ndev = nsdata->dev; | ||
285 | |||
286 | /* | ||
287 | * No need to check netif_running since we do not allow | ||
288 | * it to start up with this invalid address. | ||
289 | */ | ||
290 | if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) | ||
291 | memcpy(ndev->dev_addr, | ||
292 | local->hw.wiphy->perm_addr, | ||
293 | ETH_ALEN); | ||
294 | } | ||
295 | |||
296 | if (compare_ether_addr(null_addr, local->mdev->dev_addr) == 0) | ||
297 | memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, | ||
298 | ETH_ALEN); | ||
299 | |||
300 | /* | ||
301 | * Validate the MAC address for this device. | ||
302 | */ | ||
303 | if (!is_valid_ether_addr(dev->dev_addr)) { | ||
304 | if (!local->open_count && local->ops->stop) | ||
305 | local->ops->stop(local_to_hw(local)); | ||
306 | return -EADDRNOTAVAIL; | ||
307 | } | ||
308 | |||
273 | switch (sdata->vif.type) { | 309 | switch (sdata->vif.type) { |
274 | case IEEE80211_IF_TYPE_VLAN: | 310 | case IEEE80211_IF_TYPE_VLAN: |
275 | /* no need to tell driver */ | 311 | /* no need to tell driver */ |
@@ -975,6 +1011,8 @@ void ieee80211_if_setup(struct net_device *dev) | |||
975 | dev->open = ieee80211_open; | 1011 | dev->open = ieee80211_open; |
976 | dev->stop = ieee80211_stop; | 1012 | dev->stop = ieee80211_stop; |
977 | dev->destructor = free_netdev; | 1013 | dev->destructor = free_netdev; |
1014 | /* we will validate the address ourselves in ->open */ | ||
1015 | dev->validate_addr = NULL; | ||
978 | } | 1016 | } |
979 | 1017 | ||
980 | /* everything else */ | 1018 | /* everything else */ |