|
@@ -531,24 +531,78 @@ static int cmp_bss(struct cfg80211_bss *a,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static bool cfg80211_bss_type_match(u16 capability,
|
|
|
+ enum ieee80211_band band,
|
|
|
+ enum ieee80211_bss_type bss_type)
|
|
|
+{
|
|
|
+ bool ret = true;
|
|
|
+ u16 mask, val;
|
|
|
+
|
|
|
+ if (bss_type == IEEE80211_BSS_TYPE_ANY)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ if (band == IEEE80211_BAND_60GHZ) {
|
|
|
+ mask = WLAN_CAPABILITY_DMG_TYPE_MASK;
|
|
|
+ switch (bss_type) {
|
|
|
+ case IEEE80211_BSS_TYPE_ESS:
|
|
|
+ val = WLAN_CAPABILITY_DMG_TYPE_AP;
|
|
|
+ break;
|
|
|
+ case IEEE80211_BSS_TYPE_PBSS:
|
|
|
+ val = WLAN_CAPABILITY_DMG_TYPE_PBSS;
|
|
|
+ break;
|
|
|
+ case IEEE80211_BSS_TYPE_IBSS:
|
|
|
+ val = WLAN_CAPABILITY_DMG_TYPE_IBSS;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ mask = WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS;
|
|
|
+ switch (bss_type) {
|
|
|
+ case IEEE80211_BSS_TYPE_ESS:
|
|
|
+ val = WLAN_CAPABILITY_ESS;
|
|
|
+ break;
|
|
|
+ case IEEE80211_BSS_TYPE_IBSS:
|
|
|
+ val = WLAN_CAPABILITY_IBSS;
|
|
|
+ break;
|
|
|
+ case IEEE80211_BSS_TYPE_MBSS:
|
|
|
+ val = 0;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = ((capability & mask) == val);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
/* Returned bss is reference counted and must be cleaned up appropriately. */
|
|
|
struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
|
|
|
struct ieee80211_channel *channel,
|
|
|
const u8 *bssid,
|
|
|
const u8 *ssid, size_t ssid_len,
|
|
|
- u16 capa_mask, u16 capa_val)
|
|
|
+ enum ieee80211_bss_type bss_type,
|
|
|
+ enum ieee80211_privacy privacy)
|
|
|
{
|
|
|
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
|
|
struct cfg80211_internal_bss *bss, *res = NULL;
|
|
|
unsigned long now = jiffies;
|
|
|
+ int bss_privacy;
|
|
|
|
|
|
- trace_cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, capa_mask,
|
|
|
- capa_val);
|
|
|
+ trace_cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, bss_type,
|
|
|
+ privacy);
|
|
|
|
|
|
spin_lock_bh(&rdev->bss_lock);
|
|
|
|
|
|
list_for_each_entry(bss, &rdev->bss_list, list) {
|
|
|
- if ((bss->pub.capability & capa_mask) != capa_val)
|
|
|
+ if (!cfg80211_bss_type_match(bss->pub.capability,
|
|
|
+ bss->pub.channel->band, bss_type))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ bss_privacy = (bss->pub.capability & WLAN_CAPABILITY_PRIVACY);
|
|
|
+ if ((privacy == IEEE80211_PRIVACY_ON && !bss_privacy) ||
|
|
|
+ (privacy == IEEE80211_PRIVACY_OFF && bss_privacy))
|
|
|
continue;
|
|
|
if (channel && bss->pub.channel != channel)
|
|
|
continue;
|
|
@@ -896,6 +950,7 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
|
|
|
struct cfg80211_bss_ies *ies;
|
|
|
struct ieee80211_channel *channel;
|
|
|
struct cfg80211_internal_bss tmp = {}, *res;
|
|
|
+ int bss_type;
|
|
|
bool signal_valid;
|
|
|
|
|
|
if (WARN_ON(!wiphy))
|
|
@@ -950,8 +1005,15 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
|
|
|
if (!res)
|
|
|
return NULL;
|
|
|
|
|
|
- if (res->pub.capability & WLAN_CAPABILITY_ESS)
|
|
|
- regulatory_hint_found_beacon(wiphy, channel, gfp);
|
|
|
+ if (channel->band == IEEE80211_BAND_60GHZ) {
|
|
|
+ bss_type = res->pub.capability & WLAN_CAPABILITY_DMG_TYPE_MASK;
|
|
|
+ if (bss_type == WLAN_CAPABILITY_DMG_TYPE_AP ||
|
|
|
+ bss_type == WLAN_CAPABILITY_DMG_TYPE_PBSS)
|
|
|
+ regulatory_hint_found_beacon(wiphy, channel, gfp);
|
|
|
+ } else {
|
|
|
+ if (res->pub.capability & WLAN_CAPABILITY_ESS)
|
|
|
+ regulatory_hint_found_beacon(wiphy, channel, gfp);
|
|
|
+ }
|
|
|
|
|
|
trace_cfg80211_return_bss(&res->pub);
|
|
|
/* cfg80211_bss_update gives us a referenced result */
|
|
@@ -973,6 +1035,7 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
|
|
|
bool signal_valid;
|
|
|
size_t ielen = len - offsetof(struct ieee80211_mgmt,
|
|
|
u.probe_resp.variable);
|
|
|
+ int bss_type;
|
|
|
|
|
|
BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) !=
|
|
|
offsetof(struct ieee80211_mgmt, u.beacon.variable));
|
|
@@ -1025,8 +1088,15 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
|
|
|
if (!res)
|
|
|
return NULL;
|
|
|
|
|
|
- if (res->pub.capability & WLAN_CAPABILITY_ESS)
|
|
|
- regulatory_hint_found_beacon(wiphy, channel, gfp);
|
|
|
+ if (channel->band == IEEE80211_BAND_60GHZ) {
|
|
|
+ bss_type = res->pub.capability & WLAN_CAPABILITY_DMG_TYPE_MASK;
|
|
|
+ if (bss_type == WLAN_CAPABILITY_DMG_TYPE_AP ||
|
|
|
+ bss_type == WLAN_CAPABILITY_DMG_TYPE_PBSS)
|
|
|
+ regulatory_hint_found_beacon(wiphy, channel, gfp);
|
|
|
+ } else {
|
|
|
+ if (res->pub.capability & WLAN_CAPABILITY_ESS)
|
|
|
+ regulatory_hint_found_beacon(wiphy, channel, gfp);
|
|
|
+ }
|
|
|
|
|
|
trace_cfg80211_return_bss(&res->pub);
|
|
|
/* cfg80211_bss_update gives us a referenced result */
|