Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f126958 authored by Luciano Coelho's avatar Luciano Coelho Committed by Srinivas Dasari
Browse files

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: default avatarLuciano Coelho <luciano.coelho@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Git-commit: 256da02d1806c740be97576a5e8548d658858319
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git


CRs-fixed: 1082480
Change-Id: Ib799ce36cc4e39e0db20df978789f57ab9c8eead
Signed-off-by: default avatarSrinivas Dasari <dasaris@codeaurora.org>
parent f6a9d356
Loading
Loading
Loading
Loading
+75 −61
Original line number Original line Diff line number Diff line
@@ -5951,14 +5951,12 @@ static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
	return 0;
	return 0;
}
}


static int nl80211_start_sched_scan(struct sk_buff *skb,
static struct cfg80211_sched_scan_request *
				    struct genl_info *info)
nl80211_parse_sched_scan(struct wiphy *wiphy,
			 struct nlattr **attrs)
{
{
	struct cfg80211_sched_scan_request *request;
	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 nlattr *attr;
	struct wiphy *wiphy;
	int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i;
	int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i;
	u32 interval;
	u32 interval;
	enum ieee80211_band band;
	enum ieee80211_band band;
@@ -5966,38 +5964,32 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
	struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
	struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
	s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
	s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;


	if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
	if (!is_valid_ie_attr(attrs[NL80211_ATTR_IE]))
	    !rdev->ops->sched_scan_start)
		return ERR_PTR(-EINVAL);
		return -EOPNOTSUPP;

	if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
		return -EINVAL;


	if (!info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
	if (!attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
		return -EINVAL;
		return ERR_PTR(-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)
	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(
		n_channels = validate_scan_freqs(
				info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
				attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
		if (!n_channels)
		if (!n_channels)
			return -EINVAL;
			return ERR_PTR(-EINVAL);
	} else {
	} else {
		n_channels = ieee80211_get_num_supported_channels(wiphy);
		n_channels = ieee80211_get_num_supported_channels(wiphy);
	}
	}


	if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
	if (attrs[NL80211_ATTR_SCAN_SSIDS])
		nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS],
		nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
				    tmp)
				    tmp)
			n_ssids++;
			n_ssids++;


	if (n_ssids > wiphy->max_sched_scan_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
	 * First, count the number of 'real' matchsets. Due to an issue with
@@ -6008,9 +6000,9 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
	 * older userspace that treated a matchset with only the RSSI as the
	 * older userspace that treated a matchset with only the RSSI as the
	 * global RSSI for all other matchsets - if there are other matchsets.
	 * 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,
		nla_for_each_nested(attr,
				    info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
				    attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
				    tmp) {
				    tmp) {
			struct nlattr *rssi;
			struct nlattr *rssi;


@@ -6018,7 +6010,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
					nla_data(attr), nla_len(attr),
					nla_data(attr), nla_len(attr),
					nl80211_match_policy);
					nl80211_match_policy);
			if (err)
			if (err)
				return err;
				return ERR_PTR(err);
			/* add other standalone attributes here */
			/* add other standalone attributes here */
			if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) {
			if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) {
				n_match_sets++;
				n_match_sets++;
@@ -6035,30 +6027,23 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
		n_match_sets = 1;
		n_match_sets = 1;


	if (n_match_sets > wiphy->max_match_sets)
	if (n_match_sets > wiphy->max_match_sets)
		return -EINVAL;
		return ERR_PTR(-EINVAL);


	if (info->attrs[NL80211_ATTR_IE])
	if (attrs[NL80211_ATTR_IE])
		ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
		ie_len = nla_len(attrs[NL80211_ATTR_IE]);
	else
	else
		ie_len = 0;
		ie_len = 0;


	if (ie_len > wiphy->max_sched_scan_ie_len)
	if (ie_len > wiphy->max_sched_scan_ie_len)
		return -EINVAL;
		return ERR_PTR(-EINVAL);

	if (rdev->sched_scan_req) {
		err = -EINPROGRESS;
		goto out;
	}


	request = kzalloc(sizeof(*request)
	request = kzalloc(sizeof(*request)
			+ sizeof(*request->ssids) * n_ssids
			+ sizeof(*request->ssids) * n_ssids
			+ sizeof(*request->match_sets) * n_match_sets
			+ sizeof(*request->match_sets) * n_match_sets
			+ sizeof(*request->channels) * n_channels
			+ sizeof(*request->channels) * n_channels
			+ ie_len, GFP_KERNEL);
			+ ie_len, GFP_KERNEL);
	if (!request) {
	if (!request)
		err = -ENOMEM;
		return ERR_PTR(-ENOMEM);
		goto out;
	}


	if (n_ssids)
	if (n_ssids)
		request->ssids = (void *)&request->channels[n_channels];
		request->ssids = (void *)&request->channels[n_channels];
@@ -6083,10 +6068,10 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
	request->n_match_sets = n_match_sets;
	request->n_match_sets = n_match_sets;


	i = 0;
	i = 0;
	if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
	if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
		/* user specified, bail out if channel not found */
		/* user specified, bail out if channel not found */
		nla_for_each_nested(attr,
		nla_for_each_nested(attr,
				    info->attrs[NL80211_ATTR_SCAN_FREQUENCIES],
				    attrs[NL80211_ATTR_SCAN_FREQUENCIES],
				    tmp) {
				    tmp) {
			struct ieee80211_channel *chan;
			struct ieee80211_channel *chan;


@@ -6132,8 +6117,8 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
	request->n_channels = i;
	request->n_channels = i;


	i = 0;
	i = 0;
	if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) {
	if (attrs[NL80211_ATTR_SCAN_SSIDS]) {
		nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS],
		nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
				    tmp) {
				    tmp) {
			if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
			if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
				err = -EINVAL;
				err = -EINVAL;
@@ -6147,9 +6132,9 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
	}
	}


	i = 0;
	i = 0;
	if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
	if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
		nla_for_each_nested(attr,
		nla_for_each_nested(attr,
				    info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
				    attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
				    tmp) {
				    tmp) {
			struct nlattr *ssid, *rssi;
			struct nlattr *ssid, *rssi;


@@ -6204,13 +6189,13 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
	if (ie_len) {
	if (ie_len) {
		request->ie_len = ie_len;
		request->ie_len = ie_len;
		memcpy((void *)request->ie,
		memcpy((void *)request->ie,
		       nla_data(info->attrs[NL80211_ATTR_IE]),
		       nla_data(attrs[NL80211_ATTR_IE]),
		       request->ie_len);
		       request->ie_len);
	}
	}


	if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
	if (attrs[NL80211_ATTR_SCAN_FLAGS]) {
		request->flags = nla_get_u32(
		request->flags = nla_get_u32(
			info->attrs[NL80211_ATTR_SCAN_FLAGS]);
			attrs[NL80211_ATTR_SCAN_FLAGS]);
		if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
		if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
		    !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
		    !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
			err = -EOPNOTSUPP;
			err = -EOPNOTSUPP;
@@ -6218,25 +6203,54 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
		}
		}
	}
	}


	request->dev = dev;
	request->wiphy = &rdev->wiphy;
	request->interval = interval;
	request->interval = interval;
	request->scan_start = jiffies;
	request->scan_start = jiffies;


	err = rdev_sched_scan_start(rdev, dev, request);
	return request;
	if (!err) {

out_free:
	kfree(request);
	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;

	if (info->attrs[NL80211_ATTR_IFACE_SOCKET_OWNER])
	if (info->attrs[NL80211_ATTR_IFACE_SOCKET_OWNER])
			request->owner_nlportid = info->snd_portid;
		rdev->sched_scan_req->owner_nlportid = info->snd_portid;


		rdev->sched_scan_req = request;
	nl80211_send_sched_scan(rdev, dev,
	nl80211_send_sched_scan(rdev, dev,
				NL80211_CMD_START_SCHED_SCAN);
				NL80211_CMD_START_SCHED_SCAN);
		goto out;
	return 0;
	}


out_free:
out_free:
	kfree(request);
	kfree(rdev->sched_scan_req);
out:
out_err:
	rdev->sched_scan_req = NULL;
	return err;
	return err;
}
}