diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/debugfs_netdev.c | 16 | ||||
-rw-r--r-- | net/mac80211/ieee80211.c | 360 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 3 | ||||
-rw-r--r-- | net/mac80211/ieee80211_sta.c | 26 | ||||
-rw-r--r-- | net/mac80211/rx.c | 4 |
5 files changed, 162 insertions, 247 deletions
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 9efb84c47bb0..c9948fa58e08 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -165,20 +165,6 @@ IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); | |||
165 | /* VLAN attributes */ | 165 | /* VLAN attributes */ |
166 | IEEE80211_IF_FILE(vlan_id, u.vlan.id, DEC); | 166 | IEEE80211_IF_FILE(vlan_id, u.vlan.id, DEC); |
167 | 167 | ||
168 | /* MONITOR attributes */ | ||
169 | static ssize_t ieee80211_if_fmt_mode( | ||
170 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) | ||
171 | { | ||
172 | struct ieee80211_local *local = sdata->local; | ||
173 | |||
174 | return scnprintf(buf, buflen, "%s\n", | ||
175 | ((local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) || | ||
176 | local->open_count == local->monitors) ? | ||
177 | "hard" : "soft"); | ||
178 | } | ||
179 | __IEEE80211_IF_FILE(mode); | ||
180 | |||
181 | |||
182 | #define DEBUGFS_ADD(name, type)\ | 168 | #define DEBUGFS_ADD(name, type)\ |
183 | sdata->debugfs.type.name = debugfs_create_file(#name, 0444,\ | 169 | sdata->debugfs.type.name = debugfs_create_file(#name, 0444,\ |
184 | sdata->debugfsdir, sdata, &name##_ops); | 170 | sdata->debugfsdir, sdata, &name##_ops); |
@@ -242,7 +228,6 @@ static void add_vlan_files(struct ieee80211_sub_if_data *sdata) | |||
242 | 228 | ||
243 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) | 229 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) |
244 | { | 230 | { |
245 | DEBUGFS_ADD(mode, monitor); | ||
246 | } | 231 | } |
247 | 232 | ||
248 | static void add_files(struct ieee80211_sub_if_data *sdata) | 233 | static void add_files(struct ieee80211_sub_if_data *sdata) |
@@ -337,7 +322,6 @@ static void del_vlan_files(struct ieee80211_sub_if_data *sdata) | |||
337 | 322 | ||
338 | static void del_monitor_files(struct ieee80211_sub_if_data *sdata) | 323 | static void del_monitor_files(struct ieee80211_sub_if_data *sdata) |
339 | { | 324 | { |
340 | DEBUGFS_DEL(mode, monitor); | ||
341 | } | 325 | } |
342 | 326 | ||
343 | static void del_files(struct ieee80211_sub_if_data *sdata, int type) | 327 | static void del_files(struct ieee80211_sub_if_data *sdata, int type) |
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 57ec8880bb1a..319ec2a1d84f 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c | |||
@@ -53,6 +53,38 @@ static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr) | |||
53 | return ETH_ALEN; | 53 | return ETH_ALEN; |
54 | } | 54 | } |
55 | 55 | ||
56 | /* must be called under mdev tx lock */ | ||
57 | static void ieee80211_configure_filter(struct ieee80211_local *local) | ||
58 | { | ||
59 | unsigned int changed_flags; | ||
60 | unsigned int new_flags = 0; | ||
61 | |||
62 | if (local->iff_promiscs) | ||
63 | new_flags |= FIF_PROMISC_IN_BSS; | ||
64 | |||
65 | if (local->iff_allmultis) | ||
66 | new_flags |= FIF_ALLMULTI; | ||
67 | |||
68 | if (local->monitors) | ||
69 | new_flags |= FIF_CONTROL | | ||
70 | FIF_OTHER_BSS | | ||
71 | FIF_BCN_PRBRESP_PROMISC; | ||
72 | |||
73 | changed_flags = local->filter_flags ^ new_flags; | ||
74 | |||
75 | /* be a bit nasty */ | ||
76 | new_flags |= (1<<31); | ||
77 | |||
78 | local->ops->configure_filter(local_to_hw(local), | ||
79 | changed_flags, &new_flags, | ||
80 | local->mdev->mc_count, | ||
81 | local->mdev->mc_list); | ||
82 | |||
83 | WARN_ON(new_flags & (1<<31)); | ||
84 | |||
85 | local->filter_flags = new_flags & ~(1<<31); | ||
86 | } | ||
87 | |||
56 | /* master interface */ | 88 | /* master interface */ |
57 | 89 | ||
58 | static int ieee80211_master_open(struct net_device *dev) | 90 | static int ieee80211_master_open(struct net_device *dev) |
@@ -86,6 +118,13 @@ static int ieee80211_master_stop(struct net_device *dev) | |||
86 | return 0; | 118 | return 0; |
87 | } | 119 | } |
88 | 120 | ||
121 | static void ieee80211_master_set_multicast_list(struct net_device *dev) | ||
122 | { | ||
123 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
124 | |||
125 | ieee80211_configure_filter(local); | ||
126 | } | ||
127 | |||
89 | /* management interface */ | 128 | /* management interface */ |
90 | 129 | ||
91 | static void | 130 | static void |
@@ -267,49 +306,6 @@ static inline int identical_mac_addr_allowed(int type1, int type2) | |||
267 | type2 == IEEE80211_IF_TYPE_VLAN))); | 306 | type2 == IEEE80211_IF_TYPE_VLAN))); |
268 | } | 307 | } |
269 | 308 | ||
270 | /* Check if running monitor interfaces should go to a "soft monitor" mode | ||
271 | * and switch them if necessary. */ | ||
272 | static inline void ieee80211_start_soft_monitor(struct ieee80211_local *local) | ||
273 | { | ||
274 | struct ieee80211_if_init_conf conf; | ||
275 | |||
276 | if (local->open_count && local->open_count == local->monitors && | ||
277 | !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) && | ||
278 | local->ops->remove_interface) { | ||
279 | conf.if_id = -1; | ||
280 | conf.type = IEEE80211_IF_TYPE_MNTR; | ||
281 | conf.mac_addr = NULL; | ||
282 | local->ops->remove_interface(local_to_hw(local), &conf); | ||
283 | } | ||
284 | } | ||
285 | |||
286 | /* Check if running monitor interfaces should go to a "hard monitor" mode | ||
287 | * and switch them if necessary. */ | ||
288 | static void ieee80211_start_hard_monitor(struct ieee80211_local *local) | ||
289 | { | ||
290 | struct ieee80211_if_init_conf conf; | ||
291 | |||
292 | if (local->open_count && local->open_count == local->monitors && | ||
293 | !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER)) { | ||
294 | conf.if_id = -1; | ||
295 | conf.type = IEEE80211_IF_TYPE_MNTR; | ||
296 | conf.mac_addr = NULL; | ||
297 | local->ops->add_interface(local_to_hw(local), &conf); | ||
298 | } | ||
299 | } | ||
300 | |||
301 | static void ieee80211_if_open(struct net_device *dev) | ||
302 | { | ||
303 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
304 | |||
305 | switch (sdata->type) { | ||
306 | case IEEE80211_IF_TYPE_STA: | ||
307 | case IEEE80211_IF_TYPE_IBSS: | ||
308 | sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET; | ||
309 | break; | ||
310 | } | ||
311 | } | ||
312 | |||
313 | static int ieee80211_open(struct net_device *dev) | 309 | static int ieee80211_open(struct net_device *dev) |
314 | { | 310 | { |
315 | struct ieee80211_sub_if_data *sdata, *nsdata; | 311 | struct ieee80211_sub_if_data *sdata, *nsdata; |
@@ -335,84 +331,96 @@ static int ieee80211_open(struct net_device *dev) | |||
335 | is_zero_ether_addr(sdata->u.wds.remote_addr)) | 331 | is_zero_ether_addr(sdata->u.wds.remote_addr)) |
336 | return -ENOLINK; | 332 | return -ENOLINK; |
337 | 333 | ||
338 | if (sdata->type == IEEE80211_IF_TYPE_MNTR && local->open_count && | ||
339 | !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER)) { | ||
340 | /* run the interface in a "soft monitor" mode */ | ||
341 | local->monitors++; | ||
342 | local->open_count++; | ||
343 | local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; | ||
344 | return 0; | ||
345 | } | ||
346 | ieee80211_if_open(dev); | ||
347 | ieee80211_start_soft_monitor(local); | ||
348 | |||
349 | conf.if_id = dev->ifindex; | ||
350 | conf.type = sdata->type; | ||
351 | if (sdata->type == IEEE80211_IF_TYPE_MNTR) | ||
352 | conf.mac_addr = NULL; | ||
353 | else | ||
354 | conf.mac_addr = dev->dev_addr; | ||
355 | res = local->ops->add_interface(local_to_hw(local), &conf); | ||
356 | if (res) { | ||
357 | if (sdata->type == IEEE80211_IF_TYPE_MNTR) | ||
358 | ieee80211_start_hard_monitor(local); | ||
359 | return res; | ||
360 | } | ||
361 | |||
362 | if (local->open_count == 0) { | 334 | if (local->open_count == 0) { |
363 | res = 0; | 335 | res = 0; |
364 | tasklet_enable(&local->tx_pending_tasklet); | 336 | if (local->ops->start) |
365 | tasklet_enable(&local->tasklet); | 337 | res = local->ops->start(local_to_hw(local)); |
366 | if (local->ops->open) | 338 | if (res) |
367 | res = local->ops->open(local_to_hw(local)); | ||
368 | if (res == 0) { | ||
369 | res = dev_open(local->mdev); | ||
370 | if (res) { | ||
371 | if (local->ops->stop) | ||
372 | local->ops->stop(local_to_hw(local)); | ||
373 | } else { | ||
374 | res = ieee80211_hw_config(local); | ||
375 | if (res && local->ops->stop) | ||
376 | local->ops->stop(local_to_hw(local)); | ||
377 | else if (!res && local->apdev) | ||
378 | dev_open(local->apdev); | ||
379 | } | ||
380 | } | ||
381 | if (res) { | ||
382 | if (local->ops->remove_interface) | ||
383 | local->ops->remove_interface(local_to_hw(local), | ||
384 | &conf); | ||
385 | return res; | 339 | return res; |
386 | } | ||
387 | } | 340 | } |
388 | local->open_count++; | ||
389 | 341 | ||
390 | if (sdata->type == IEEE80211_IF_TYPE_MNTR) { | 342 | switch (sdata->type) { |
343 | case IEEE80211_IF_TYPE_MNTR: | ||
344 | /* must be before the call to ieee80211_configure_filter */ | ||
391 | local->monitors++; | 345 | local->monitors++; |
392 | local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; | 346 | if (local->monitors == 1) { |
393 | } else { | 347 | netif_tx_lock_bh(local->mdev); |
348 | ieee80211_configure_filter(local); | ||
349 | netif_tx_unlock_bh(local->mdev); | ||
350 | |||
351 | local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; | ||
352 | ieee80211_hw_config(local); | ||
353 | } | ||
354 | break; | ||
355 | case IEEE80211_IF_TYPE_STA: | ||
356 | case IEEE80211_IF_TYPE_IBSS: | ||
357 | sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET; | ||
358 | /* fall through */ | ||
359 | default: | ||
360 | conf.if_id = dev->ifindex; | ||
361 | conf.type = sdata->type; | ||
362 | conf.mac_addr = dev->dev_addr; | ||
363 | res = local->ops->add_interface(local_to_hw(local), &conf); | ||
364 | if (res && !local->open_count && local->ops->stop) | ||
365 | local->ops->stop(local_to_hw(local)); | ||
366 | if (res) | ||
367 | return res; | ||
368 | |||
394 | ieee80211_if_config(dev); | 369 | ieee80211_if_config(dev); |
395 | ieee80211_reset_erp_info(dev); | 370 | ieee80211_reset_erp_info(dev); |
396 | ieee80211_enable_keys(sdata); | 371 | ieee80211_enable_keys(sdata); |
372 | |||
373 | if (sdata->type == IEEE80211_IF_TYPE_STA && | ||
374 | !local->user_space_mlme) | ||
375 | netif_carrier_off(dev); | ||
376 | else | ||
377 | netif_carrier_on(dev); | ||
397 | } | 378 | } |
398 | 379 | ||
399 | if (sdata->type == IEEE80211_IF_TYPE_STA && | 380 | if (local->open_count == 0) { |
400 | !local->user_space_mlme) | 381 | res = dev_open(local->mdev); |
401 | netif_carrier_off(dev); | 382 | WARN_ON(res); |
402 | else | 383 | if (local->apdev) { |
403 | netif_carrier_on(dev); | 384 | res = dev_open(local->apdev); |
385 | WARN_ON(res); | ||
386 | } | ||
387 | tasklet_enable(&local->tx_pending_tasklet); | ||
388 | tasklet_enable(&local->tasklet); | ||
389 | } | ||
390 | |||
391 | local->open_count++; | ||
404 | 392 | ||
405 | netif_start_queue(dev); | 393 | netif_start_queue(dev); |
394 | |||
406 | return 0; | 395 | return 0; |
407 | } | 396 | } |
408 | 397 | ||
409 | static void ieee80211_if_shutdown(struct net_device *dev) | 398 | static int ieee80211_stop(struct net_device *dev) |
410 | { | 399 | { |
400 | struct ieee80211_sub_if_data *sdata; | ||
411 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 401 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
412 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 402 | struct ieee80211_if_init_conf conf; |
403 | |||
404 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
405 | |||
406 | netif_stop_queue(dev); | ||
407 | |||
408 | dev_mc_unsync(local->mdev, dev); | ||
409 | |||
410 | local->open_count--; | ||
413 | 411 | ||
414 | ASSERT_RTNL(); | ||
415 | switch (sdata->type) { | 412 | switch (sdata->type) { |
413 | case IEEE80211_IF_TYPE_MNTR: | ||
414 | local->monitors--; | ||
415 | if (local->monitors == 0) { | ||
416 | netif_tx_lock_bh(local->mdev); | ||
417 | ieee80211_configure_filter(local); | ||
418 | netif_tx_unlock_bh(local->mdev); | ||
419 | |||
420 | local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; | ||
421 | ieee80211_hw_config(local); | ||
422 | } | ||
423 | break; | ||
416 | case IEEE80211_IF_TYPE_STA: | 424 | case IEEE80211_IF_TYPE_STA: |
417 | case IEEE80211_IF_TYPE_IBSS: | 425 | case IEEE80211_IF_TYPE_IBSS: |
418 | sdata->u.sta.state = IEEE80211_DISABLED; | 426 | sdata->u.sta.state = IEEE80211_DISABLED; |
@@ -433,116 +441,61 @@ static void ieee80211_if_shutdown(struct net_device *dev) | |||
433 | cancel_delayed_work(&local->scan_work); | 441 | cancel_delayed_work(&local->scan_work); |
434 | } | 442 | } |
435 | flush_workqueue(local->hw.workqueue); | 443 | flush_workqueue(local->hw.workqueue); |
436 | break; | 444 | /* fall through */ |
437 | } | 445 | default: |
438 | } | 446 | conf.if_id = dev->ifindex; |
439 | 447 | conf.type = sdata->type; | |
440 | static int ieee80211_stop(struct net_device *dev) | 448 | conf.mac_addr = dev->dev_addr; |
441 | { | ||
442 | struct ieee80211_sub_if_data *sdata; | ||
443 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
444 | |||
445 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
446 | |||
447 | if (sdata->type == IEEE80211_IF_TYPE_MNTR && | ||
448 | local->open_count > 1 && | ||
449 | !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER)) { | ||
450 | /* remove "soft monitor" interface */ | ||
451 | local->open_count--; | ||
452 | local->monitors--; | ||
453 | if (!local->monitors) | ||
454 | local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; | ||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | netif_stop_queue(dev); | ||
459 | ieee80211_if_shutdown(dev); | ||
460 | |||
461 | if (sdata->type == IEEE80211_IF_TYPE_MNTR) { | ||
462 | local->monitors--; | ||
463 | if (!local->monitors) | ||
464 | local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; | ||
465 | } else { | ||
466 | /* disable all keys for as long as this netdev is down */ | 449 | /* disable all keys for as long as this netdev is down */ |
467 | ieee80211_disable_keys(sdata); | 450 | ieee80211_disable_keys(sdata); |
451 | local->ops->remove_interface(local_to_hw(local), &conf); | ||
468 | } | 452 | } |
469 | 453 | ||
470 | local->open_count--; | ||
471 | if (local->open_count == 0) { | 454 | if (local->open_count == 0) { |
472 | if (netif_running(local->mdev)) | 455 | if (netif_running(local->mdev)) |
473 | dev_close(local->mdev); | 456 | dev_close(local->mdev); |
457 | |||
474 | if (local->apdev) | 458 | if (local->apdev) |
475 | dev_close(local->apdev); | 459 | dev_close(local->apdev); |
460 | |||
476 | if (local->ops->stop) | 461 | if (local->ops->stop) |
477 | local->ops->stop(local_to_hw(local)); | 462 | local->ops->stop(local_to_hw(local)); |
463 | |||
478 | tasklet_disable(&local->tx_pending_tasklet); | 464 | tasklet_disable(&local->tx_pending_tasklet); |
479 | tasklet_disable(&local->tasklet); | 465 | tasklet_disable(&local->tasklet); |
480 | } | 466 | } |
481 | if (local->ops->remove_interface) { | ||
482 | struct ieee80211_if_init_conf conf; | ||
483 | |||
484 | conf.if_id = dev->ifindex; | ||
485 | conf.type = sdata->type; | ||
486 | conf.mac_addr = dev->dev_addr; | ||
487 | local->ops->remove_interface(local_to_hw(local), &conf); | ||
488 | } | ||
489 | |||
490 | ieee80211_start_hard_monitor(local); | ||
491 | 467 | ||
492 | return 0; | 468 | return 0; |
493 | } | 469 | } |
494 | 470 | ||
495 | enum netif_tx_lock_class { | ||
496 | TX_LOCK_NORMAL, | ||
497 | TX_LOCK_MASTER, | ||
498 | }; | ||
499 | |||
500 | static inline void netif_tx_lock_nested(struct net_device *dev, int subclass) | ||
501 | { | ||
502 | spin_lock_nested(&dev->_xmit_lock, subclass); | ||
503 | dev->xmit_lock_owner = smp_processor_id(); | ||
504 | } | ||
505 | |||
506 | static void ieee80211_set_multicast_list(struct net_device *dev) | 471 | static void ieee80211_set_multicast_list(struct net_device *dev) |
507 | { | 472 | { |
508 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 473 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
509 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 474 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
510 | unsigned short flags; | 475 | int allmulti, promisc, sdata_allmulti, sdata_promisc; |
511 | 476 | ||
512 | netif_tx_lock_nested(local->mdev, TX_LOCK_MASTER); | 477 | allmulti = !!(dev->flags & IFF_ALLMULTI); |
513 | if (((dev->flags & IFF_ALLMULTI) != 0) ^ | 478 | promisc = !!(dev->flags & IFF_PROMISC); |
514 | ((sdata->flags & IEEE80211_SDATA_ALLMULTI) != 0)) { | 479 | sdata_allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI; |
515 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | 480 | sdata_promisc = sdata->flags & IEEE80211_SDATA_PROMISC; |
516 | local->iff_allmultis--; | 481 | |
517 | else | 482 | if (allmulti != sdata_allmulti) { |
483 | if (dev->flags & IFF_ALLMULTI) | ||
518 | local->iff_allmultis++; | 484 | local->iff_allmultis++; |
485 | else | ||
486 | local->iff_allmultis--; | ||
519 | sdata->flags ^= IEEE80211_SDATA_ALLMULTI; | 487 | sdata->flags ^= IEEE80211_SDATA_ALLMULTI; |
520 | } | 488 | } |
521 | if (((dev->flags & IFF_PROMISC) != 0) ^ | 489 | |
522 | ((sdata->flags & IEEE80211_SDATA_PROMISC) != 0)) { | 490 | if (promisc != sdata_promisc) { |
523 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | 491 | if (dev->flags & IFF_PROMISC) |
524 | local->iff_promiscs--; | ||
525 | else | ||
526 | local->iff_promiscs++; | 492 | local->iff_promiscs++; |
493 | else | ||
494 | local->iff_promiscs--; | ||
527 | sdata->flags ^= IEEE80211_SDATA_PROMISC; | 495 | sdata->flags ^= IEEE80211_SDATA_PROMISC; |
528 | } | 496 | } |
529 | if (dev->mc_count != sdata->mc_count) { | 497 | |
530 | local->mc_count = local->mc_count - sdata->mc_count + | 498 | dev_mc_sync(local->mdev, dev); |
531 | dev->mc_count; | ||
532 | sdata->mc_count = dev->mc_count; | ||
533 | } | ||
534 | if (local->ops->set_multicast_list) { | ||
535 | flags = local->mdev->flags; | ||
536 | if (local->iff_allmultis) | ||
537 | flags |= IFF_ALLMULTI; | ||
538 | if (local->iff_promiscs) | ||
539 | flags |= IFF_PROMISC; | ||
540 | read_lock(&local->sub_if_lock); | ||
541 | local->ops->set_multicast_list(local_to_hw(local), flags, | ||
542 | local->mc_count); | ||
543 | read_unlock(&local->sub_if_lock); | ||
544 | } | ||
545 | netif_tx_unlock(local->mdev); | ||
546 | } | 499 | } |
547 | 500 | ||
548 | static const struct header_ops ieee80211_header_ops = { | 501 | static const struct header_ops ieee80211_header_ops = { |
@@ -612,7 +565,6 @@ static int __ieee80211_if_config(struct net_device *dev, | |||
612 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 565 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
613 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 566 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
614 | struct ieee80211_if_conf conf; | 567 | struct ieee80211_if_conf conf; |
615 | static u8 scan_bssid[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
616 | 568 | ||
617 | if (!local->ops->config_interface || !netif_running(dev)) | 569 | if (!local->ops->config_interface || !netif_running(dev)) |
618 | return 0; | 570 | return 0; |
@@ -621,11 +573,7 @@ static int __ieee80211_if_config(struct net_device *dev, | |||
621 | conf.type = sdata->type; | 573 | conf.type = sdata->type; |
622 | if (sdata->type == IEEE80211_IF_TYPE_STA || | 574 | if (sdata->type == IEEE80211_IF_TYPE_STA || |
623 | sdata->type == IEEE80211_IF_TYPE_IBSS) { | 575 | sdata->type == IEEE80211_IF_TYPE_IBSS) { |
624 | if (local->sta_scanning && | 576 | conf.bssid = sdata->u.sta.bssid; |
625 | local->scan_dev == dev) | ||
626 | conf.bssid = scan_bssid; | ||
627 | else | ||
628 | conf.bssid = sdata->u.sta.bssid; | ||
629 | conf.ssid = sdata->u.sta.ssid; | 577 | conf.ssid = sdata->u.sta.ssid; |
630 | conf.ssid_len = sdata->u.sta.ssid_len; | 578 | conf.ssid_len = sdata->u.sta.ssid_len; |
631 | conf.generic_elem = sdata->u.sta.extra_ie; | 579 | conf.generic_elem = sdata->u.sta.extra_ie; |
@@ -722,37 +670,6 @@ void ieee80211_reset_erp_info(struct net_device *dev) | |||
722 | IEEE80211_ERP_CHANGE_PREAMBLE); | 670 | IEEE80211_ERP_CHANGE_PREAMBLE); |
723 | } | 671 | } |
724 | 672 | ||
725 | struct dev_mc_list *ieee80211_get_mc_list_item(struct ieee80211_hw *hw, | ||
726 | struct dev_mc_list *prev, | ||
727 | void **ptr) | ||
728 | { | ||
729 | struct ieee80211_local *local = hw_to_local(hw); | ||
730 | struct ieee80211_sub_if_data *sdata = *ptr; | ||
731 | struct dev_mc_list *mc; | ||
732 | |||
733 | if (!prev) { | ||
734 | WARN_ON(sdata); | ||
735 | sdata = NULL; | ||
736 | } | ||
737 | if (!prev || !prev->next) { | ||
738 | if (sdata) | ||
739 | sdata = list_entry(sdata->list.next, | ||
740 | struct ieee80211_sub_if_data, list); | ||
741 | else | ||
742 | sdata = list_entry(local->sub_if_list.next, | ||
743 | struct ieee80211_sub_if_data, list); | ||
744 | if (&sdata->list != &local->sub_if_list) | ||
745 | mc = sdata->dev->mc_list; | ||
746 | else | ||
747 | mc = NULL; | ||
748 | } else | ||
749 | mc = prev->next; | ||
750 | |||
751 | *ptr = sdata; | ||
752 | return mc; | ||
753 | } | ||
754 | EXPORT_SYMBOL(ieee80211_get_mc_list_item); | ||
755 | |||
756 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, | 673 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, |
757 | struct sk_buff *skb, | 674 | struct sk_buff *skb, |
758 | struct ieee80211_tx_status *status) | 675 | struct ieee80211_tx_status *status) |
@@ -1158,8 +1075,12 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
1158 | NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); | 1075 | NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); |
1159 | 1076 | ||
1160 | BUG_ON(!ops->tx); | 1077 | BUG_ON(!ops->tx); |
1078 | BUG_ON(!ops->start); | ||
1079 | BUG_ON(!ops->stop); | ||
1161 | BUG_ON(!ops->config); | 1080 | BUG_ON(!ops->config); |
1162 | BUG_ON(!ops->add_interface); | 1081 | BUG_ON(!ops->add_interface); |
1082 | BUG_ON(!ops->remove_interface); | ||
1083 | BUG_ON(!ops->configure_filter); | ||
1163 | local->ops = ops; | 1084 | local->ops = ops; |
1164 | 1085 | ||
1165 | /* for now, mdev needs sub_if_data :/ */ | 1086 | /* for now, mdev needs sub_if_data :/ */ |
@@ -1206,6 +1127,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
1206 | mdev->stop = ieee80211_master_stop; | 1127 | mdev->stop = ieee80211_master_stop; |
1207 | mdev->type = ARPHRD_IEEE80211; | 1128 | mdev->type = ARPHRD_IEEE80211; |
1208 | mdev->header_ops = &ieee80211_header_ops; | 1129 | mdev->header_ops = &ieee80211_header_ops; |
1130 | mdev->set_multicast_list = ieee80211_master_set_multicast_list; | ||
1209 | 1131 | ||
1210 | sdata->type = IEEE80211_IF_TYPE_AP; | 1132 | sdata->type = IEEE80211_IF_TYPE_AP; |
1211 | sdata->dev = mdev; | 1133 | sdata->dev = mdev; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c3f6f89755b1..74deecd09677 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -297,8 +297,6 @@ struct ieee80211_sub_if_data { | |||
297 | struct net_device *dev; | 297 | struct net_device *dev; |
298 | struct ieee80211_local *local; | 298 | struct ieee80211_local *local; |
299 | 299 | ||
300 | int mc_count; | ||
301 | |||
302 | unsigned int flags; | 300 | unsigned int flags; |
303 | 301 | ||
304 | int drop_unencrypted; | 302 | int drop_unencrypted; |
@@ -411,6 +409,7 @@ struct ieee80211_local { | |||
411 | struct net_device *apdev; /* wlan#ap - management frames (hostapd) */ | 409 | struct net_device *apdev; /* wlan#ap - management frames (hostapd) */ |
412 | int open_count; | 410 | int open_count; |
413 | int monitors; | 411 | int monitors; |
412 | unsigned int filter_flags; /* FIF_* */ | ||
414 | struct iw_statistics wstats; | 413 | struct iw_statistics wstats; |
415 | u8 wstats_flags; | 414 | u8 wstats_flags; |
416 | int tx_headroom; /* required headroom for hardware/radiotap */ | 415 | int tx_headroom; /* required headroom for hardware/radiotap */ |
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index 3f0a2faf37d4..17455c6a5229 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c | |||
@@ -2662,10 +2662,16 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) | |||
2662 | printk(KERN_DEBUG "%s: failed to restore operational" | 2662 | printk(KERN_DEBUG "%s: failed to restore operational" |
2663 | "channel after scan\n", dev->name); | 2663 | "channel after scan\n", dev->name); |
2664 | 2664 | ||
2665 | if (!(local->hw.flags & IEEE80211_HW_NO_PROBE_FILTERING) && | 2665 | |
2666 | ieee80211_if_config(dev)) | 2666 | netif_tx_lock_bh(local->mdev); |
2667 | printk(KERN_DEBUG "%s: failed to restore operational" | 2667 | local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; |
2668 | "BSSID after scan\n", dev->name); | 2668 | local->ops->configure_filter(local_to_hw(local), |
2669 | FIF_BCN_PRBRESP_PROMISC, | ||
2670 | &local->filter_flags, | ||
2671 | local->mdev->mc_count, | ||
2672 | local->mdev->mc_list); | ||
2673 | |||
2674 | netif_tx_unlock_bh(local->mdev); | ||
2669 | 2675 | ||
2670 | memset(&wrqu, 0, sizeof(wrqu)); | 2676 | memset(&wrqu, 0, sizeof(wrqu)); |
2671 | wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); | 2677 | wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); |
@@ -2849,10 +2855,14 @@ static int ieee80211_sta_start_scan(struct net_device *dev, | |||
2849 | local->scan_channel_idx = 0; | 2855 | local->scan_channel_idx = 0; |
2850 | local->scan_dev = dev; | 2856 | local->scan_dev = dev; |
2851 | 2857 | ||
2852 | if (!(local->hw.flags & IEEE80211_HW_NO_PROBE_FILTERING) && | 2858 | netif_tx_lock_bh(local->mdev); |
2853 | ieee80211_if_config(dev)) | 2859 | local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; |
2854 | printk(KERN_DEBUG "%s: failed to set BSSID for scan\n", | 2860 | local->ops->configure_filter(local_to_hw(local), |
2855 | dev->name); | 2861 | FIF_BCN_PRBRESP_PROMISC, |
2862 | &local->filter_flags, | ||
2863 | local->mdev->mc_count, | ||
2864 | local->mdev->mc_list); | ||
2865 | netif_tx_unlock_bh(local->mdev); | ||
2856 | 2866 | ||
2857 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ | 2867 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ |
2858 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | 2868 | queue_delayed_work(local->hw.workqueue, &local->scan_work, |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index b5f2e4c25c7e..2535d8d4ce90 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1307,7 +1307,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1307 | } else if (!multicast && | 1307 | } else if (!multicast && |
1308 | compare_ether_addr(sdata->dev->dev_addr, | 1308 | compare_ether_addr(sdata->dev->dev_addr, |
1309 | hdr->addr1) != 0) { | 1309 | hdr->addr1) != 0) { |
1310 | if (!(sdata->flags & IEEE80211_SDATA_PROMISC)) | 1310 | if (!(sdata->dev->flags & IFF_PROMISC)) |
1311 | return 0; | 1311 | return 0; |
1312 | rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; | 1312 | rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; |
1313 | } | 1313 | } |
@@ -1322,7 +1322,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1322 | } else if (!multicast && | 1322 | } else if (!multicast && |
1323 | compare_ether_addr(sdata->dev->dev_addr, | 1323 | compare_ether_addr(sdata->dev->dev_addr, |
1324 | hdr->addr1) != 0) { | 1324 | hdr->addr1) != 0) { |
1325 | if (!(sdata->flags & IEEE80211_SDATA_PROMISC)) | 1325 | if (!(sdata->dev->flags & IFF_PROMISC)) |
1326 | return 0; | 1326 | return 0; |
1327 | rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; | 1327 | rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; |
1328 | } else if (!rx->sta) | 1328 | } else if (!rx->sta) |