Commit 3007e352 authored by Arend Van Spriel's avatar Arend Van Spriel Committed by Johannes Berg

nl80211: add support for BSSIDs in scheduled scan matchsets

This patch allows for the scheduled scan request to specify matchsets
for specific BSSIDs.
Reviewed-by: default avatarHante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: default avatarFranky Lin <franky.lin@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend.vanspriel@broadcom.com>
[docs, netlink policy fix]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent ca986ad9
...@@ -1613,11 +1613,15 @@ static inline void get_random_mask_addr(u8 *buf, const u8 *addr, const u8 *mask) ...@@ -1613,11 +1613,15 @@ static inline void get_random_mask_addr(u8 *buf, const u8 *addr, const u8 *mask)
/** /**
* struct cfg80211_match_set - sets of attributes to match * struct cfg80211_match_set - sets of attributes to match
* *
* @ssid: SSID to be matched; may be zero-length for no match (RSSI only) * @ssid: SSID to be matched; may be zero-length in case of BSSID match
* or no match (RSSI only)
* @bssid: BSSID to be matched; may be all-zero BSSID in case of SSID match
* or no match (RSSI only)
* @rssi_thold: don't report scan results below this threshold (in s32 dBm) * @rssi_thold: don't report scan results below this threshold (in s32 dBm)
*/ */
struct cfg80211_match_set { struct cfg80211_match_set {
struct cfg80211_ssid ssid; struct cfg80211_ssid ssid;
u8 bssid[ETH_ALEN];
s32 rssi_thold; s32 rssi_thold;
}; };
......
...@@ -3194,6 +3194,7 @@ enum nl80211_reg_rule_attr { ...@@ -3194,6 +3194,7 @@ enum nl80211_reg_rule_attr {
* @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved
* @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching, * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching,
* only report BSS with matching SSID. * only report BSS with matching SSID.
* (This cannot be used together with BSSID.)
* @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: RSSI threshold (in dBm) for reporting a * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: RSSI threshold (in dBm) for reporting a
* BSS in scan results. Filtering is turned off if not specified. Note that * BSS in scan results. Filtering is turned off if not specified. Note that
* if this attribute is in a match set of its own, then it is treated as * if this attribute is in a match set of its own, then it is treated as
...@@ -3209,6 +3210,8 @@ enum nl80211_reg_rule_attr { ...@@ -3209,6 +3210,8 @@ enum nl80211_reg_rule_attr {
* BSS-es in the specified band is to be adjusted before doing * BSS-es in the specified band is to be adjusted before doing
* RSSI-based BSS selection. The attribute value is a packed structure * RSSI-based BSS selection. The attribute value is a packed structure
* value as specified by &struct nl80211_bss_select_rssi_adjust. * value as specified by &struct nl80211_bss_select_rssi_adjust.
* @NL80211_SCHED_SCAN_MATCH_ATTR_BSSID: BSSID to be used for matching
* (this cannot be used together with SSID).
* @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
* attribute number currently defined * attribute number currently defined
* @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
...@@ -3220,6 +3223,7 @@ enum nl80211_sched_scan_match_attr { ...@@ -3220,6 +3223,7 @@ enum nl80211_sched_scan_match_attr {
NL80211_SCHED_SCAN_MATCH_ATTR_RSSI, NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI, NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI,
NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST, NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST,
NL80211_SCHED_SCAN_MATCH_ATTR_BSSID,
/* keep last */ /* keep last */
__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST, __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST,
......
...@@ -497,6 +497,7 @@ static const struct nla_policy ...@@ -497,6 +497,7 @@ static const struct nla_policy
nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = { nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] = { .type = NLA_BINARY, [NL80211_SCHED_SCAN_MATCH_ATTR_SSID] = { .type = NLA_BINARY,
.len = IEEE80211_MAX_SSID_LEN }, .len = IEEE80211_MAX_SSID_LEN },
[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID] = { .len = ETH_ALEN },
[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 }, [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },
}; };
...@@ -7036,8 +7037,15 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev, ...@@ -7036,8 +7037,15 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
NULL); NULL);
if (err) if (err)
return ERR_PTR(err); return ERR_PTR(err);
/* SSID and BSSID are mutually exclusive */
if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] &&
tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID])
return ERR_PTR(-EINVAL);
/* 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] ||
tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID]) {
n_match_sets++; n_match_sets++;
continue; continue;
} }
...@@ -7208,7 +7216,7 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev, ...@@ -7208,7 +7216,7 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
nla_for_each_nested(attr, nla_for_each_nested(attr,
attrs[NL80211_ATTR_SCHED_SCAN_MATCH], attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
tmp) { tmp) {
struct nlattr *ssid, *rssi; struct nlattr *ssid, *bssid, *rssi;
err = nla_parse_nested(tb, err = nla_parse_nested(tb,
NL80211_SCHED_SCAN_MATCH_ATTR_MAX, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
...@@ -7217,7 +7225,8 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev, ...@@ -7217,7 +7225,8 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
if (err) if (err)
goto out_free; goto out_free;
ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]; ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
if (ssid) { bssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID];
if (ssid || bssid) {
if (WARN_ON(i >= n_match_sets)) { if (WARN_ON(i >= n_match_sets)) {
/* this indicates a programming error, /* this indicates a programming error,
* the loop above should have verified * the loop above should have verified
...@@ -7227,14 +7236,25 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev, ...@@ -7227,14 +7236,25 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
goto out_free; goto out_free;
} }
if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) { if (ssid) {
err = -EINVAL; if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) {
goto out_free; err = -EINVAL;
goto out_free;
}
memcpy(request->match_sets[i].ssid.ssid,
nla_data(ssid), nla_len(ssid));
request->match_sets[i].ssid.ssid_len =
nla_len(ssid);
}
if (bssid) {
if (nla_len(bssid) != ETH_ALEN) {
err = -EINVAL;
goto out_free;
}
memcpy(request->match_sets[i].bssid,
nla_data(bssid), ETH_ALEN);
} }
memcpy(request->match_sets[i].ssid.ssid,
nla_data(ssid), nla_len(ssid));
request->match_sets[i].ssid.ssid_len =
nla_len(ssid);
/* special attribute - old implementation w/a */ /* special attribute - old implementation w/a */
request->match_sets[i].rssi_thold = request->match_sets[i].rssi_thold =
default_match_rssi; default_match_rssi;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment