summaryrefslogtreecommitdiff
path: root/net/mac80211/ieee80211.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2007-09-17 09:29:24 +0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-11 03:52:57 +0400
commit0ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5 (patch)
treea9e5fab14a3f928df6536a913ca8aba5e0ab2632 /net/mac80211/ieee80211.c
parent4150c57212ad134765dd78c654a4b9906252b66d (diff)
downloadlinux-0ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5.tar.xz
[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)
int res;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
read_lock(&local->sub_if_lock);
list_for_each_entry(nsdata, &local->sub_if_list, list) {
struct net_device *ndev = nsdata->dev;
if (ndev != dev && ndev != local->mdev && netif_running(ndev) &&
- compare_ether_addr(dev->dev_addr, ndev->dev_addr) == 0 &&
- !identical_mac_addr_allowed(sdata->type, nsdata->type)) {
- read_unlock(&local->sub_if_lock);
- return -ENOTUNIQ;
+ compare_ether_addr(dev->dev_addr, ndev->dev_addr) == 0) {
+ /*
+ * check whether it may have the same address
+ */
+ if (!identical_mac_addr_allowed(sdata->type,
+ nsdata->type)) {
+ read_unlock(&local->sub_if_lock);
+ return -ENOTUNIQ;
+ }
+
+ /*
+ * can only add VLANs to enabled APs
+ */
+ if (sdata->type == IEEE80211_IF_TYPE_VLAN &&
+ nsdata->type == IEEE80211_IF_TYPE_AP &&
+ netif_running(nsdata->dev))
+ sdata->u.vlan.ap = nsdata;
}
}
read_unlock(&local->sub_if_lock);
- if (sdata->type == IEEE80211_IF_TYPE_WDS &&
- is_zero_ether_addr(sdata->u.wds.remote_addr))
- return -ENOLINK;
+ switch (sdata->type) {
+ case IEEE80211_IF_TYPE_WDS:
+ if (is_zero_ether_addr(sdata->u.wds.remote_addr))
+ return -ENOLINK;
+ break;
+ case IEEE80211_IF_TYPE_VLAN:
+ if (!sdata->u.vlan.ap)
+ return -ENOLINK;
+ break;
+ }
if (local->open_count == 0) {
res = 0;
@@ -340,6 +361,10 @@ static int ieee80211_open(struct net_device *dev)
}
switch (sdata->type) {
+ case IEEE80211_IF_TYPE_VLAN:
+ list_add(&sdata->u.vlan.list, &sdata->u.vlan.ap->u.ap.vlans);
+ /* no need to tell driver */
+ break;
case IEEE80211_IF_TYPE_MNTR:
/* must be before the call to ieee80211_configure_filter */
local->monitors++;
@@ -407,9 +432,24 @@ static int ieee80211_stop(struct net_device *dev)
dev_mc_unsync(local->mdev, dev);
+ /* down all dependent devices, that is VLANs */
+ if (sdata->type == IEEE80211_IF_TYPE_AP) {
+ struct ieee80211_sub_if_data *vlan, *tmp;
+
+ list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans,
+ u.vlan.list)
+ dev_close(vlan->dev);
+ WARN_ON(!list_empty(&sdata->u.ap.vlans));
+ }
+
local->open_count--;
switch (sdata->type) {
+ case IEEE80211_IF_TYPE_VLAN:
+ list_del(&sdata->u.vlan.list);
+ sdata->u.vlan.ap = NULL;
+ /* no need to tell driver */
+ break;
case IEEE80211_IF_TYPE_MNTR:
local->monitors--;
if (local->monitors == 0) {