aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h17
-rw-r--r--net/mac80211/debugfs_netdev.c5
-rw-r--r--net/mac80211/ieee80211.c54
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/ieee80211_iface.c5
5 files changed, 65 insertions, 22 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 855754d4c50d..494a4c022a9b 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -442,16 +442,17 @@ struct ieee80211_conf {
442 * @IEEE80211_IF_TYPE_IBSS: interface in IBSS (ad-hoc) mode. 442 * @IEEE80211_IF_TYPE_IBSS: interface in IBSS (ad-hoc) mode.
443 * @IEEE80211_IF_TYPE_MNTR: interface in monitor (rfmon) mode. 443 * @IEEE80211_IF_TYPE_MNTR: interface in monitor (rfmon) mode.
444 * @IEEE80211_IF_TYPE_WDS: interface in WDS mode. 444 * @IEEE80211_IF_TYPE_WDS: interface in WDS mode.
445 * @IEEE80211_IF_TYPE_VLAN: not used. 445 * @IEEE80211_IF_TYPE_VLAN: VLAN interface bound to an AP, drivers
446 * will never see this type.
446 */ 447 */
447enum ieee80211_if_types { 448enum ieee80211_if_types {
448 IEEE80211_IF_TYPE_AP = 0x00000000, 449 IEEE80211_IF_TYPE_AP,
449 IEEE80211_IF_TYPE_MGMT = 0x00000001, 450 IEEE80211_IF_TYPE_MGMT,
450 IEEE80211_IF_TYPE_STA = 0x00000002, 451 IEEE80211_IF_TYPE_STA,
451 IEEE80211_IF_TYPE_IBSS = 0x00000003, 452 IEEE80211_IF_TYPE_IBSS,
452 IEEE80211_IF_TYPE_MNTR = 0x00000004, 453 IEEE80211_IF_TYPE_MNTR,
453 IEEE80211_IF_TYPE_WDS = 0x5A580211, 454 IEEE80211_IF_TYPE_WDS,
454 IEEE80211_IF_TYPE_VLAN = 0x00080211, 455 IEEE80211_IF_TYPE_VLAN,
455}; 456};
456 457
457/** 458/**
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index c9948fa58e08..f0e6ab7eb624 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -162,9 +162,6 @@ __IEEE80211_IF_FILE(beacon_tail_len);
162/* WDS attributes */ 162/* WDS attributes */
163IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); 163IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
164 164
165/* VLAN attributes */
166IEEE80211_IF_FILE(vlan_id, u.vlan.id, DEC);
167
168#define DEBUGFS_ADD(name, type)\ 165#define DEBUGFS_ADD(name, type)\
169 sdata->debugfs.type.name = debugfs_create_file(#name, 0444,\ 166 sdata->debugfs.type.name = debugfs_create_file(#name, 0444,\
170 sdata->debugfsdir, sdata, &name##_ops); 167 sdata->debugfsdir, sdata, &name##_ops);
@@ -223,7 +220,6 @@ static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
223 DEBUGFS_ADD(drop_unencrypted, vlan); 220 DEBUGFS_ADD(drop_unencrypted, vlan);
224 DEBUGFS_ADD(eapol, vlan); 221 DEBUGFS_ADD(eapol, vlan);
225 DEBUGFS_ADD(ieee8021_x, vlan); 222 DEBUGFS_ADD(ieee8021_x, vlan);
226 DEBUGFS_ADD(vlan_id, vlan);
227} 223}
228 224
229static void add_monitor_files(struct ieee80211_sub_if_data *sdata) 225static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
@@ -317,7 +313,6 @@ static void del_vlan_files(struct ieee80211_sub_if_data *sdata)
317 DEBUGFS_DEL(drop_unencrypted, vlan); 313 DEBUGFS_DEL(drop_unencrypted, vlan);
318 DEBUGFS_DEL(eapol, vlan); 314 DEBUGFS_DEL(eapol, vlan);
319 DEBUGFS_DEL(ieee8021_x, vlan); 315 DEBUGFS_DEL(ieee8021_x, vlan);
320 DEBUGFS_DEL(vlan_id, vlan);
321} 316}
322 317
323static void del_monitor_files(struct ieee80211_sub_if_data *sdata) 318static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
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) {
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 74deecd09677..1a43f3e9b6bd 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -191,6 +191,8 @@ struct ieee80211_if_ap {
191 u8 *beacon_head, *beacon_tail; 191 u8 *beacon_head, *beacon_tail;
192 int beacon_head_len, beacon_tail_len; 192 int beacon_head_len, beacon_tail_len;
193 193
194 struct list_head vlans;
195
194 u8 ssid[IEEE80211_MAX_SSID_LEN]; 196 u8 ssid[IEEE80211_MAX_SSID_LEN];
195 size_t ssid_len; 197 size_t ssid_len;
196 u8 *generic_elem; 198 u8 *generic_elem;
@@ -214,7 +216,8 @@ struct ieee80211_if_wds {
214}; 216};
215 217
216struct ieee80211_if_vlan { 218struct ieee80211_if_vlan {
217 u8 id; 219 struct ieee80211_sub_if_data *ap;
220 struct list_head list;
218}; 221};
219 222
220/* flags used in struct ieee80211_if_sta.flags */ 223/* flags used in struct ieee80211_if_sta.flags */
@@ -377,7 +380,6 @@ struct ieee80211_sub_if_data {
377 struct dentry *drop_unencrypted; 380 struct dentry *drop_unencrypted;
378 struct dentry *eapol; 381 struct dentry *eapol;
379 struct dentry *ieee8021_x; 382 struct dentry *ieee8021_x;
380 struct dentry *vlan_id;
381 } vlan; 383 } vlan;
382 struct { 384 struct {
383 struct dentry *mode; 385 struct dentry *mode;
diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c
index f9c74bb09d31..4590205fdf4b 100644
--- a/net/mac80211/ieee80211_iface.c
+++ b/net/mac80211/ieee80211_iface.c
@@ -164,6 +164,7 @@ void ieee80211_if_set_type(struct net_device *dev, int type)
164 sdata->bss = NULL; 164 sdata->bss = NULL;
165 break; 165 break;
166 case IEEE80211_IF_TYPE_VLAN: 166 case IEEE80211_IF_TYPE_VLAN:
167 sdata->u.vlan.ap = NULL;
167 break; 168 break;
168 case IEEE80211_IF_TYPE_AP: 169 case IEEE80211_IF_TYPE_AP:
169 sdata->u.ap.dtim_period = 2; 170 sdata->u.ap.dtim_period = 2;
@@ -171,6 +172,7 @@ void ieee80211_if_set_type(struct net_device *dev, int type)
171 sdata->u.ap.max_ratectrl_rateidx = -1; 172 sdata->u.ap.max_ratectrl_rateidx = -1;
172 skb_queue_head_init(&sdata->u.ap.ps_bc_buf); 173 skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
173 sdata->bss = &sdata->u.ap; 174 sdata->bss = &sdata->u.ap;
175 INIT_LIST_HEAD(&sdata->u.ap.vlans);
174 break; 176 break;
175 case IEEE80211_IF_TYPE_STA: 177 case IEEE80211_IF_TYPE_STA:
176 case IEEE80211_IF_TYPE_IBSS: { 178 case IEEE80211_IF_TYPE_IBSS: {
@@ -284,6 +286,9 @@ void ieee80211_if_reinit(struct net_device *dev)
284 case IEEE80211_IF_TYPE_MNTR: 286 case IEEE80211_IF_TYPE_MNTR:
285 dev->type = ARPHRD_ETHER; 287 dev->type = ARPHRD_ETHER;
286 break; 288 break;
289 case IEEE80211_IF_TYPE_VLAN:
290 sdata->u.vlan.ap = NULL;
291 break;
287 } 292 }
288 293
289 /* remove all STAs that are bound to this virtual interface */ 294 /* remove all STAs that are bound to this virtual interface */