aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/ieee80211.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2007-09-17 01:29:24 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:52:57 -0400
commit0ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5 (patch)
treea9e5fab14a3f928df6536a913ca8aba5e0ab2632 /net/mac80211/ieee80211.c
parent4150c57212ad134765dd78c654a4b9906252b66d (diff)
[PATCH] mac80211: validate VLAN interfaces better
This patch changes mac80211 to verify that VLAN interfaces are valid and not bother drivers about them any more. VLAN interfaces are now only valid when an AP interface is up with the same MAC address, and are automatically turned off when the AP interface is set down. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Cc: Jouni Malinen <j@w1.fi> Signed-off-by: Michael Wu <flamingice@sourmilk.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/ieee80211.c')
-rw-r--r--net/mac80211/ieee80211.c54
1 files changed, 47 insertions, 7 deletions
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 319ec2a1d84f..4e345f82f044 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -314,22 +314,43 @@ static int ieee80211_open(struct net_device *dev)
314 int res; 314 int res;
315 315
316 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 316 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
317
317 read_lock(&local->sub_if_lock); 318 read_lock(&local->sub_if_lock);
318 list_for_each_entry(nsdata, &local->sub_if_list, list) { 319 list_for_each_entry(nsdata, &local->sub_if_list, list) {
319 struct net_device *ndev = nsdata->dev; 320 struct net_device *ndev = nsdata->dev;
320 321
321 if (ndev != dev && ndev != local->mdev && netif_running(ndev) && 322 if (ndev != dev && ndev != local->mdev && netif_running(ndev) &&
322 compare_ether_addr(dev->dev_addr, ndev->dev_addr) == 0 && 323 compare_ether_addr(dev->dev_addr, ndev->dev_addr) == 0) {
323 !identical_mac_addr_allowed(sdata->type, nsdata->type)) { 324 /*
324 read_unlock(&local->sub_if_lock); 325 * check whether it may have the same address
325 return -ENOTUNIQ; 326 */
327 if (!identical_mac_addr_allowed(sdata->type,
328 nsdata->type)) {
329 read_unlock(&local->sub_if_lock);
330 return -ENOTUNIQ;
331 }
332
333 /*
334 * can only add VLANs to enabled APs
335 */
336 if (sdata->type == IEEE80211_IF_TYPE_VLAN &&
337 nsdata->type == IEEE80211_IF_TYPE_AP &&
338 netif_running(nsdata->dev))
339 sdata->u.vlan.ap = nsdata;
326 } 340 }
327 } 341 }
328 read_unlock(&local->sub_if_lock); 342 read_unlock(&local->sub_if_lock);
329 343
330 if (sdata->type == IEEE80211_IF_TYPE_WDS && 344 switch (sdata->type) {
331 is_zero_ether_addr(sdata->u.wds.remote_addr)) 345 case IEEE80211_IF_TYPE_WDS:
332 return -ENOLINK; 346 if (is_zero_ether_addr(sdata->u.wds.remote_addr))
347 return -ENOLINK;
348 break;
349 case IEEE80211_IF_TYPE_VLAN:
350 if (!sdata->u.vlan.ap)
351 return -ENOLINK;
352 break;
353 }
333 354
334 if (local->open_count == 0) { 355 if (local->open_count == 0) {
335 res = 0; 356 res = 0;
@@ -340,6 +361,10 @@ static int ieee80211_open(struct net_device *dev)
340 } 361 }
341 362
342 switch (sdata->type) { 363 switch (sdata->type) {
364 case IEEE80211_IF_TYPE_VLAN:
365 list_add(&sdata->u.vlan.list, &sdata->u.vlan.ap->u.ap.vlans);
366 /* no need to tell driver */
367 break;
343 case IEEE80211_IF_TYPE_MNTR: 368 case IEEE80211_IF_TYPE_MNTR:
344 /* must be before the call to ieee80211_configure_filter */ 369 /* must be before the call to ieee80211_configure_filter */
345 local->monitors++; 370 local->monitors++;
@@ -407,9 +432,24 @@ static int ieee80211_stop(struct net_device *dev)
407 432
408 dev_mc_unsync(local->mdev, dev); 433 dev_mc_unsync(local->mdev, dev);
409 434
435 /* down all dependent devices, that is VLANs */
436 if (sdata->type == IEEE80211_IF_TYPE_AP) {
437 struct ieee80211_sub_if_data *vlan, *tmp;
438
439 list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans,
440 u.vlan.list)
441 dev_close(vlan->dev);
442 WARN_ON(!list_empty(&sdata->u.ap.vlans));
443 }
444
410 local->open_count--; 445 local->open_count--;
411 446
412 switch (sdata->type) { 447 switch (sdata->type) {
448 case IEEE80211_IF_TYPE_VLAN:
449 list_del(&sdata->u.vlan.list);
450 sdata->u.vlan.ap = NULL;
451 /* no need to tell driver */
452 break;
413 case IEEE80211_IF_TYPE_MNTR: 453 case IEEE80211_IF_TYPE_MNTR:
414 local->monitors--; 454 local->monitors--;
415 if (local->monitors == 0) { 455 if (local->monitors == 0) {