diff options
| author | Jukka Rissanen <jukka.rissanen@linux.intel.com> | 2014-12-15 06:25:39 -0500 |
|---|---|---|
| committer | Johannes Berg <johannes.berg@intel.com> | 2014-12-18 08:38:44 -0500 |
| commit | 93a1e86ce10e4898f9ca9cd09d659a8a7780ee5e (patch) | |
| tree | 42155b15af02c90d9c824ffbc2d3ad8b6d4a9b34 /net/wireless | |
| parent | 31a60ed1e95ab8afbadb65599bef12b195080a0c (diff) | |
nl80211: Stop scheduled scan if netlink client disappears
An attribute NL80211_ATTR_SOCKET_OWNER can be set by the scan initiator.
If present, the attribute will cause the scan to be stopped if the client
dies.
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
| -rw-r--r-- | net/wireless/core.c | 16 | ||||
| -rw-r--r-- | net/wireless/core.h | 2 | ||||
| -rw-r--r-- | net/wireless/nl80211.c | 16 |
3 files changed, 34 insertions, 0 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index 0743449405ca..456e4c38c279 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
| @@ -321,6 +321,20 @@ static void cfg80211_destroy_iface_wk(struct work_struct *work) | |||
| 321 | rtnl_unlock(); | 321 | rtnl_unlock(); |
| 322 | } | 322 | } |
| 323 | 323 | ||
| 324 | static void cfg80211_sched_scan_stop_wk(struct work_struct *work) | ||
| 325 | { | ||
| 326 | struct cfg80211_registered_device *rdev; | ||
| 327 | |||
| 328 | rdev = container_of(work, struct cfg80211_registered_device, | ||
| 329 | sched_scan_stop_wk); | ||
| 330 | |||
| 331 | rtnl_lock(); | ||
| 332 | |||
| 333 | __cfg80211_stop_sched_scan(rdev, false); | ||
| 334 | |||
| 335 | rtnl_unlock(); | ||
| 336 | } | ||
| 337 | |||
| 324 | /* exported functions */ | 338 | /* exported functions */ |
| 325 | 339 | ||
| 326 | struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, | 340 | struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, |
| @@ -407,6 +421,7 @@ use_default_name: | |||
| 407 | INIT_LIST_HEAD(&rdev->destroy_list); | 421 | INIT_LIST_HEAD(&rdev->destroy_list); |
| 408 | spin_lock_init(&rdev->destroy_list_lock); | 422 | spin_lock_init(&rdev->destroy_list_lock); |
| 409 | INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk); | 423 | INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk); |
| 424 | INIT_WORK(&rdev->sched_scan_stop_wk, cfg80211_sched_scan_stop_wk); | ||
| 410 | 425 | ||
| 411 | #ifdef CONFIG_CFG80211_DEFAULT_PS | 426 | #ifdef CONFIG_CFG80211_DEFAULT_PS |
| 412 | rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; | 427 | rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; |
| @@ -787,6 +802,7 @@ void wiphy_unregister(struct wiphy *wiphy) | |||
| 787 | flush_work(&rdev->event_work); | 802 | flush_work(&rdev->event_work); |
| 788 | cancel_delayed_work_sync(&rdev->dfs_update_channels_wk); | 803 | cancel_delayed_work_sync(&rdev->dfs_update_channels_wk); |
| 789 | flush_work(&rdev->destroy_work); | 804 | flush_work(&rdev->destroy_work); |
| 805 | flush_work(&rdev->sched_scan_stop_wk); | ||
| 790 | 806 | ||
| 791 | #ifdef CONFIG_PM | 807 | #ifdef CONFIG_PM |
| 792 | if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup) | 808 | if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup) |
diff --git a/net/wireless/core.h b/net/wireless/core.h index e82030c32311..801cd49c5a0c 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
| @@ -91,6 +91,8 @@ struct cfg80211_registered_device { | |||
| 91 | struct list_head destroy_list; | 91 | struct list_head destroy_list; |
| 92 | struct work_struct destroy_work; | 92 | struct work_struct destroy_work; |
| 93 | 93 | ||
| 94 | struct work_struct sched_scan_stop_wk; | ||
| 95 | |||
| 94 | /* must be last because of the way we do wiphy_priv(), | 96 | /* must be last because of the way we do wiphy_priv(), |
| 95 | * and it should at least be aligned to NETDEV_ALIGN */ | 97 | * and it should at least be aligned to NETDEV_ALIGN */ |
| 96 | struct wiphy wiphy __aligned(NETDEV_ALIGN); | 98 | struct wiphy wiphy __aligned(NETDEV_ALIGN); |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index bacdf22fa472..702920134b34 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -6214,6 +6214,9 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
| 6214 | sched_scan_req->dev = dev; | 6214 | sched_scan_req->dev = dev; |
| 6215 | sched_scan_req->wiphy = &rdev->wiphy; | 6215 | sched_scan_req->wiphy = &rdev->wiphy; |
| 6216 | 6216 | ||
| 6217 | if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) | ||
| 6218 | sched_scan_req->owner_nlportid = info->snd_portid; | ||
| 6219 | |||
| 6217 | rcu_assign_pointer(rdev->sched_scan_req, sched_scan_req); | 6220 | rcu_assign_pointer(rdev->sched_scan_req, sched_scan_req); |
| 6218 | 6221 | ||
| 6219 | nl80211_send_sched_scan(rdev, dev, | 6222 | nl80211_send_sched_scan(rdev, dev, |
| @@ -12618,6 +12621,13 @@ static int nl80211_netlink_notify(struct notifier_block * nb, | |||
| 12618 | 12621 | ||
| 12619 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) { | 12622 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) { |
| 12620 | bool schedule_destroy_work = false; | 12623 | bool schedule_destroy_work = false; |
| 12624 | bool schedule_scan_stop = false; | ||
| 12625 | struct cfg80211_sched_scan_request *sched_scan_req = | ||
| 12626 | rcu_dereference(rdev->sched_scan_req); | ||
| 12627 | |||
| 12628 | if (sched_scan_req && notify->portid && | ||
| 12629 | sched_scan_req->owner_nlportid == notify->portid) | ||
| 12630 | schedule_scan_stop = true; | ||
| 12621 | 12631 | ||
| 12622 | list_for_each_entry_rcu(wdev, &rdev->wdev_list, list) { | 12632 | list_for_each_entry_rcu(wdev, &rdev->wdev_list, list) { |
| 12623 | cfg80211_mlme_unregister_socket(wdev, notify->portid); | 12633 | cfg80211_mlme_unregister_socket(wdev, notify->portid); |
| @@ -12648,6 +12658,12 @@ static int nl80211_netlink_notify(struct notifier_block * nb, | |||
| 12648 | spin_unlock(&rdev->destroy_list_lock); | 12658 | spin_unlock(&rdev->destroy_list_lock); |
| 12649 | schedule_work(&rdev->destroy_work); | 12659 | schedule_work(&rdev->destroy_work); |
| 12650 | } | 12660 | } |
| 12661 | } else if (schedule_scan_stop) { | ||
| 12662 | sched_scan_req->owner_nlportid = 0; | ||
| 12663 | |||
| 12664 | if (rdev->ops->sched_scan_stop && | ||
| 12665 | rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) | ||
| 12666 | schedule_work(&rdev->sched_scan_stop_wk); | ||
| 12651 | } | 12667 | } |
| 12652 | } | 12668 | } |
| 12653 | 12669 | ||
