@@ -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
*
- * @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)
*/
struct cfg80211_match_set {
struct cfg80211_ssid ssid;
+ u8 bssid[ETH_ALEN];
s32 rssi_thold;
};
@@ -3209,6 +3209,7 @@ enum nl80211_reg_rule_attr {
* BSS-es in the specified band is to be adjusted before doing
* RSSI-based BSS selection. The attribute value is a packed structure
* value as specified by &struct nl80211_bss_select_rssi_adjust.
+ * @NL80211_SCHED_SCAN_MATCH_ATTR_BSSID: BSSID to be used for matching.
* @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
* attribute number currently defined
* @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
@@ -3220,6 +3221,7 @@ enum nl80211_sched_scan_match_attr {
NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI,
NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST,
+ NL80211_SCHED_SCAN_MATCH_ATTR_BSSID,
/* keep last */
__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST,
@@ -497,6 +497,8 @@ enum nl80211_multicast_groups {
nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] = { .type = NLA_BINARY,
.len = IEEE80211_MAX_SSID_LEN },
+ [NL80211_SCHED_SCAN_MATCH_ATTR_BSSID] = { .type = NLA_BINARY,
+ .len = ETH_ALEN },
[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },
};
@@ -7056,8 +7058,15 @@ static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
NULL);
if (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 */
- 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++;
continue;
}
@@ -7228,7 +7237,7 @@ static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
nla_for_each_nested(attr,
attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
tmp) {
- struct nlattr *ssid, *rssi;
+ struct nlattr *ssid, *bssid, *rssi;
err = nla_parse_nested(tb,
NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
@@ -7237,7 +7246,8 @@ static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
if (err)
goto out_free;
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)) {
/* this indicates a programming error,
* the loop above should have verified
@@ -7247,14 +7257,25 @@ static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
goto out_free;
}
- if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) {
- err = -EINVAL;
- goto out_free;
+ if (ssid) {
+ if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) {
+ 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 */
request->match_sets[i].rssi_thold =
default_match_rssi;