aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorLuciano Coelho <luciano.coelho@intel.com>2014-11-10 09:13:46 -0500
committerJohannes Berg <johannes.berg@intel.com>2014-11-19 12:45:42 -0500
commit256da02d1806c740be97576a5e8548d658858319 (patch)
tree18eb9845e6f71eeec8b3c6b4e917f66971c3e9f5 /net/wireless
parentb6da911b3cf1d342f2f7123c9eb6463d299bca4e (diff)
cfg80211: refactor nl80211_start_sched_scan so it can be reused
For net detect, we will need to reuse most of the scheduled scan parsing function, but not all, so split out the attributes parsing part out of the main start sched_scan function. Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c130
1 files changed, 72 insertions, 58 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 27666f5e5050..03a302b884fd 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5681,14 +5681,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
5681 return err; 5681 return err;
5682} 5682}
5683 5683
5684static int nl80211_start_sched_scan(struct sk_buff *skb, 5684static struct cfg80211_sched_scan_request *
5685 struct genl_info *info) 5685nl80211_parse_sched_scan(struct wiphy *wiphy,
5686 struct nlattr **attrs)
5686{ 5687{
5687 struct cfg80211_sched_scan_request *request; 5688 struct cfg80211_sched_scan_request *request;
5688 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5689 struct net_device *dev = info->user_ptr[1];
5690 struct nlattr *attr; 5689 struct nlattr *attr;
5691 struct wiphy *wiphy;
5692 int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i; 5690 int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i;
5693 u32 interval; 5691 u32 interval;
5694 enum ieee80211_band band; 5692 enum ieee80211_band band;
@@ -5696,38 +5694,32 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
5696 struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1]; 5694 struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
5697 s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF; 5695 s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
5698 5696
5699 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || 5697 if (!is_valid_ie_attr(attrs[NL80211_ATTR_IE]))
5700 !rdev->ops->sched_scan_start) 5698 return ERR_PTR(-EINVAL);
5701 return -EOPNOTSUPP;
5702
5703 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
5704 return -EINVAL;
5705 5699
5706 if (!info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]) 5700 if (!attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
5707 return -EINVAL; 5701 return ERR_PTR(-EINVAL);
5708 5702
5709 interval = nla_get_u32(info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]); 5703 interval = nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]);
5710 if (interval == 0) 5704 if (interval == 0)
5711 return -EINVAL; 5705 return ERR_PTR(-EINVAL);
5712
5713 wiphy = &rdev->wiphy;
5714 5706
5715 if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { 5707 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
5716 n_channels = validate_scan_freqs( 5708 n_channels = validate_scan_freqs(
5717 info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]); 5709 attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
5718 if (!n_channels) 5710 if (!n_channels)
5719 return -EINVAL; 5711 return ERR_PTR(-EINVAL);
5720 } else { 5712 } else {
5721 n_channels = ieee80211_get_num_supported_channels(wiphy); 5713 n_channels = ieee80211_get_num_supported_channels(wiphy);
5722 } 5714 }
5723 5715
5724 if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) 5716 if (attrs[NL80211_ATTR_SCAN_SSIDS])
5725 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], 5717 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
5726 tmp) 5718 tmp)
5727 n_ssids++; 5719 n_ssids++;
5728 5720
5729 if (n_ssids > wiphy->max_sched_scan_ssids) 5721 if (n_ssids > wiphy->max_sched_scan_ssids)
5730 return -EINVAL; 5722 return ERR_PTR(-EINVAL);
5731 5723
5732 /* 5724 /*
5733 * First, count the number of 'real' matchsets. Due to an issue with 5725 * First, count the number of 'real' matchsets. Due to an issue with
@@ -5738,9 +5730,9 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
5738 * older userspace that treated a matchset with only the RSSI as the 5730 * older userspace that treated a matchset with only the RSSI as the
5739 * global RSSI for all other matchsets - if there are other matchsets. 5731 * global RSSI for all other matchsets - if there are other matchsets.
5740 */ 5732 */
5741 if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) { 5733 if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
5742 nla_for_each_nested(attr, 5734 nla_for_each_nested(attr,
5743 info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH], 5735 attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
5744 tmp) { 5736 tmp) {
5745 struct nlattr *rssi; 5737 struct nlattr *rssi;
5746 5738
@@ -5748,7 +5740,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
5748 nla_data(attr), nla_len(attr), 5740 nla_data(attr), nla_len(attr),
5749 nl80211_match_policy); 5741 nl80211_match_policy);
5750 if (err) 5742 if (err)
5751 return err; 5743 return ERR_PTR(err);
5752 /* add other standalone attributes here */ 5744 /* add other standalone attributes here */
5753 if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) { 5745 if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) {
5754 n_match_sets++; 5746 n_match_sets++;
@@ -5765,30 +5757,23 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
5765 n_match_sets = 1; 5757 n_match_sets = 1;
5766 5758
5767 if (n_match_sets > wiphy->max_match_sets) 5759 if (n_match_sets > wiphy->max_match_sets)
5768 return -EINVAL; 5760 return ERR_PTR(-EINVAL);
5769 5761
5770 if (info->attrs[NL80211_ATTR_IE]) 5762 if (attrs[NL80211_ATTR_IE])
5771 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); 5763 ie_len = nla_len(attrs[NL80211_ATTR_IE]);
5772 else 5764 else
5773 ie_len = 0; 5765 ie_len = 0;
5774 5766
5775 if (ie_len > wiphy->max_sched_scan_ie_len) 5767 if (ie_len > wiphy->max_sched_scan_ie_len)
5776 return -EINVAL; 5768 return ERR_PTR(-EINVAL);
5777
5778 if (rdev->sched_scan_req) {
5779 err = -EINPROGRESS;
5780 goto out;
5781 }
5782 5769
5783 request = kzalloc(sizeof(*request) 5770 request = kzalloc(sizeof(*request)
5784 + sizeof(*request->ssids) * n_ssids 5771 + sizeof(*request->ssids) * n_ssids
5785 + sizeof(*request->match_sets) * n_match_sets 5772 + sizeof(*request->match_sets) * n_match_sets
5786 + sizeof(*request->channels) * n_channels 5773 + sizeof(*request->channels) * n_channels
5787 + ie_len, GFP_KERNEL); 5774 + ie_len, GFP_KERNEL);
5788 if (!request) { 5775 if (!request)
5789 err = -ENOMEM; 5776 return ERR_PTR(-ENOMEM);
5790 goto out;
5791 }
5792 5777
5793 if (n_ssids) 5778 if (n_ssids)
5794 request->ssids = (void *)&request->channels[n_channels]; 5779 request->ssids = (void *)&request->channels[n_channels];
@@ -5813,10 +5798,10 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
5813 request->n_match_sets = n_match_sets; 5798 request->n_match_sets = n_match_sets;
5814 5799
5815 i = 0; 5800 i = 0;
5816 if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { 5801 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
5817 /* user specified, bail out if channel not found */ 5802 /* user specified, bail out if channel not found */
5818 nla_for_each_nested(attr, 5803 nla_for_each_nested(attr,
5819 info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], 5804 attrs[NL80211_ATTR_SCAN_FREQUENCIES],
5820 tmp) { 5805 tmp) {
5821 struct ieee80211_channel *chan; 5806 struct ieee80211_channel *chan;
5822 5807
@@ -5862,8 +5847,8 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
5862 request->n_channels = i; 5847 request->n_channels = i;
5863 5848
5864 i = 0; 5849 i = 0;
5865 if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) { 5850 if (attrs[NL80211_ATTR_SCAN_SSIDS]) {
5866 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], 5851 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
5867 tmp) { 5852 tmp) {
5868 if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) { 5853 if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
5869 err = -EINVAL; 5854 err = -EINVAL;
@@ -5877,9 +5862,9 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
5877 } 5862 }
5878 5863
5879 i = 0; 5864 i = 0;
5880 if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) { 5865 if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
5881 nla_for_each_nested(attr, 5866 nla_for_each_nested(attr,
5882 info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH], 5867 attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
5883 tmp) { 5868 tmp) {
5884 struct nlattr *ssid, *rssi; 5869 struct nlattr *ssid, *rssi;
5885 5870
@@ -5934,13 +5919,13 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
5934 if (ie_len) { 5919 if (ie_len) {
5935 request->ie_len = ie_len; 5920 request->ie_len = ie_len;
5936 memcpy((void *)request->ie, 5921 memcpy((void *)request->ie,
5937 nla_data(info->attrs[NL80211_ATTR_IE]), 5922 nla_data(attrs[NL80211_ATTR_IE]),
5938 request->ie_len); 5923 request->ie_len);
5939 } 5924 }
5940 5925
5941 if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) { 5926 if (attrs[NL80211_ATTR_SCAN_FLAGS]) {
5942 request->flags = nla_get_u32( 5927 request->flags = nla_get_u32(
5943 info->attrs[NL80211_ATTR_SCAN_FLAGS]); 5928 attrs[NL80211_ATTR_SCAN_FLAGS]);
5944 if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) && 5929 if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
5945 !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) { 5930 !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
5946 err = -EOPNOTSUPP; 5931 err = -EOPNOTSUPP;
@@ -5948,22 +5933,51 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
5948 } 5933 }
5949 } 5934 }
5950 5935
5951 request->dev = dev;
5952 request->wiphy = &rdev->wiphy;
5953 request->interval = interval; 5936 request->interval = interval;
5954 request->scan_start = jiffies; 5937 request->scan_start = jiffies;
5955 5938
5956 err = rdev_sched_scan_start(rdev, dev, request); 5939 return request;
5957 if (!err) {
5958 rdev->sched_scan_req = request;
5959 nl80211_send_sched_scan(rdev, dev,
5960 NL80211_CMD_START_SCHED_SCAN);
5961 goto out;
5962 }
5963 5940
5964out_free: 5941out_free:
5965 kfree(request); 5942 kfree(request);
5966out: 5943 return ERR_PTR(err);
5944}
5945
5946static int nl80211_start_sched_scan(struct sk_buff *skb,
5947 struct genl_info *info)
5948{
5949 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5950 struct net_device *dev = info->user_ptr[1];
5951 int err;
5952
5953 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
5954 !rdev->ops->sched_scan_start)
5955 return -EOPNOTSUPP;
5956
5957 if (rdev->sched_scan_req)
5958 return -EINPROGRESS;
5959
5960 rdev->sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy,
5961 info->attrs);
5962 err = PTR_ERR_OR_ZERO(rdev->sched_scan_req);
5963 if (err)
5964 goto out_err;
5965
5966 err = rdev_sched_scan_start(rdev, dev, rdev->sched_scan_req);
5967 if (err)
5968 goto out_free;
5969
5970 rdev->sched_scan_req->dev = dev;
5971 rdev->sched_scan_req->wiphy = &rdev->wiphy;
5972
5973 nl80211_send_sched_scan(rdev, dev,
5974 NL80211_CMD_START_SCHED_SCAN);
5975 return 0;
5976
5977out_free:
5978 kfree(rdev->sched_scan_req);
5979out_err:
5980 rdev->sched_scan_req = NULL;
5967 return err; 5981 return err;
5968} 5982}
5969 5983