mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-12 21:44:06 +08:00
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>
This commit is contained in:
parent
b6da911b3c
commit
256da02d18
@ -5681,14 +5681,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nl80211_start_sched_scan(struct sk_buff *skb,
|
||||
struct genl_info *info)
|
||||
static struct cfg80211_sched_scan_request *
|
||||
nl80211_parse_sched_scan(struct wiphy *wiphy,
|
||||
struct nlattr **attrs)
|
||||
{
|
||||
struct cfg80211_sched_scan_request *request;
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
struct nlattr *attr;
|
||||
struct wiphy *wiphy;
|
||||
int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i;
|
||||
u32 interval;
|
||||
enum ieee80211_band band;
|
||||
@ -5696,38 +5694,32 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
||||
struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
|
||||
s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
|
||||
|
||||
if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
|
||||
!rdev->ops->sched_scan_start)
|
||||
return -EOPNOTSUPP;
|
||||
if (!is_valid_ie_attr(attrs[NL80211_ATTR_IE]))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
|
||||
return -EINVAL;
|
||||
if (!attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (!info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
|
||||
return -EINVAL;
|
||||
|
||||
interval = nla_get_u32(info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]);
|
||||
interval = nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]);
|
||||
if (interval == 0)
|
||||
return -EINVAL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
wiphy = &rdev->wiphy;
|
||||
|
||||
if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
|
||||
if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
|
||||
n_channels = validate_scan_freqs(
|
||||
info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
|
||||
attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
|
||||
if (!n_channels)
|
||||
return -EINVAL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
} else {
|
||||
n_channels = ieee80211_get_num_supported_channels(wiphy);
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
|
||||
nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS],
|
||||
if (attrs[NL80211_ATTR_SCAN_SSIDS])
|
||||
nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
|
||||
tmp)
|
||||
n_ssids++;
|
||||
|
||||
if (n_ssids > wiphy->max_sched_scan_ssids)
|
||||
return -EINVAL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/*
|
||||
* 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,
|
||||
* older userspace that treated a matchset with only the RSSI as the
|
||||
* global RSSI for all other matchsets - if there are other matchsets.
|
||||
*/
|
||||
if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
|
||||
if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
|
||||
nla_for_each_nested(attr,
|
||||
info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
|
||||
attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
|
||||
tmp) {
|
||||
struct nlattr *rssi;
|
||||
|
||||
@ -5748,7 +5740,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
||||
nla_data(attr), nla_len(attr),
|
||||
nl80211_match_policy);
|
||||
if (err)
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
/* add other standalone attributes here */
|
||||
if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) {
|
||||
n_match_sets++;
|
||||
@ -5765,30 +5757,23 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
||||
n_match_sets = 1;
|
||||
|
||||
if (n_match_sets > wiphy->max_match_sets)
|
||||
return -EINVAL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (info->attrs[NL80211_ATTR_IE])
|
||||
ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
|
||||
if (attrs[NL80211_ATTR_IE])
|
||||
ie_len = nla_len(attrs[NL80211_ATTR_IE]);
|
||||
else
|
||||
ie_len = 0;
|
||||
|
||||
if (ie_len > wiphy->max_sched_scan_ie_len)
|
||||
return -EINVAL;
|
||||
|
||||
if (rdev->sched_scan_req) {
|
||||
err = -EINPROGRESS;
|
||||
goto out;
|
||||
}
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
request = kzalloc(sizeof(*request)
|
||||
+ sizeof(*request->ssids) * n_ssids
|
||||
+ sizeof(*request->match_sets) * n_match_sets
|
||||
+ sizeof(*request->channels) * n_channels
|
||||
+ ie_len, GFP_KERNEL);
|
||||
if (!request) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (!request)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
if (n_ssids)
|
||||
request->ssids = (void *)&request->channels[n_channels];
|
||||
@ -5813,10 +5798,10 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
||||
request->n_match_sets = n_match_sets;
|
||||
|
||||
i = 0;
|
||||
if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
|
||||
if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
|
||||
/* user specified, bail out if channel not found */
|
||||
nla_for_each_nested(attr,
|
||||
info->attrs[NL80211_ATTR_SCAN_FREQUENCIES],
|
||||
attrs[NL80211_ATTR_SCAN_FREQUENCIES],
|
||||
tmp) {
|
||||
struct ieee80211_channel *chan;
|
||||
|
||||
@ -5862,8 +5847,8 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
||||
request->n_channels = i;
|
||||
|
||||
i = 0;
|
||||
if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) {
|
||||
nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS],
|
||||
if (attrs[NL80211_ATTR_SCAN_SSIDS]) {
|
||||
nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
|
||||
tmp) {
|
||||
if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
|
||||
err = -EINVAL;
|
||||
@ -5877,9 +5862,9 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
||||
}
|
||||
|
||||
i = 0;
|
||||
if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
|
||||
if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
|
||||
nla_for_each_nested(attr,
|
||||
info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
|
||||
attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
|
||||
tmp) {
|
||||
struct nlattr *ssid, *rssi;
|
||||
|
||||
@ -5934,13 +5919,13 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
||||
if (ie_len) {
|
||||
request->ie_len = ie_len;
|
||||
memcpy((void *)request->ie,
|
||||
nla_data(info->attrs[NL80211_ATTR_IE]),
|
||||
nla_data(attrs[NL80211_ATTR_IE]),
|
||||
request->ie_len);
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
|
||||
if (attrs[NL80211_ATTR_SCAN_FLAGS]) {
|
||||
request->flags = nla_get_u32(
|
||||
info->attrs[NL80211_ATTR_SCAN_FLAGS]);
|
||||
attrs[NL80211_ATTR_SCAN_FLAGS]);
|
||||
if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
|
||||
!(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
|
||||
err = -EOPNOTSUPP;
|
||||
@ -5948,22 +5933,51 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
||||
}
|
||||
}
|
||||
|
||||
request->dev = dev;
|
||||
request->wiphy = &rdev->wiphy;
|
||||
request->interval = interval;
|
||||
request->scan_start = jiffies;
|
||||
|
||||
err = rdev_sched_scan_start(rdev, dev, request);
|
||||
if (!err) {
|
||||
rdev->sched_scan_req = request;
|
||||
nl80211_send_sched_scan(rdev, dev,
|
||||
NL80211_CMD_START_SCHED_SCAN);
|
||||
goto out;
|
||||
}
|
||||
return request;
|
||||
|
||||
out_free:
|
||||
kfree(request);
|
||||
out:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static int nl80211_start_sched_scan(struct sk_buff *skb,
|
||||
struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
int err;
|
||||
|
||||
if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
|
||||
!rdev->ops->sched_scan_start)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (rdev->sched_scan_req)
|
||||
return -EINPROGRESS;
|
||||
|
||||
rdev->sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy,
|
||||
info->attrs);
|
||||
err = PTR_ERR_OR_ZERO(rdev->sched_scan_req);
|
||||
if (err)
|
||||
goto out_err;
|
||||
|
||||
err = rdev_sched_scan_start(rdev, dev, rdev->sched_scan_req);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
||||
rdev->sched_scan_req->dev = dev;
|
||||
rdev->sched_scan_req->wiphy = &rdev->wiphy;
|
||||
|
||||
nl80211_send_sched_scan(rdev, dev,
|
||||
NL80211_CMD_START_SCHED_SCAN);
|
||||
return 0;
|
||||
|
||||
out_free:
|
||||
kfree(rdev->sched_scan_req);
|
||||
out_err:
|
||||
rdev->sched_scan_req = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user