mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 08:15:07 -04:00
wifi: cfg80211: say why the auth/assoc BSS lookup failed
The BSS lookup for an authentication or association request can fail
for three distinct reasons: cfg80211 has no scan entry at all for the
BSSID/channel, an entry exists but is older than
IEEE80211_SCAN_RESULT_EXPIRE (and not held), or a fresh entry exists
but its use_for flags do not allow this use. All three currently
surface as the same generic extack message "Error fetching BSS for
link" on the MLO association path, and as a bare -ENOENT with no
message at all on the authentication and non-MLO association paths.
Since wpa_supplicant logs the extack message verbatim ("nl80211:
kernel reports: ..."), that message is often the only diagnostic a
user sees when an MLO association degrades to fewer links, and it
does not say whether a fresh scan could have helped. In practice the
expired case is common for MLO partner links: 6 GHz is passive-scan
in many regulatory domains, so the partner-link entry is routinely
stale by the time userspace requests the association even though the
link is perfectly usable.
Let __cfg80211_get_bss() take an optional extack and record, during
the same bss_lock walk that fails the lookup, whether any matching
entry was rejected for being expired or for not being usable for the
requested use, and set a distinct message for each case (and a
combined one when different entries were rejected for different
reasons). Reorder the checks in the walk so that an entry's identity
(type, privacy, channel, BSSID/SSID) is established before the
usability checks; this doesn't change which entry is returned since
an entry is only used when all checks pass.
Also give the -EINVAL paths in nl80211_assoc_bss() proper messages
while at it, and keep pointing the bad_attr at the failing link on
the MLO path there; the message for that case is already set by the
lookup itself.
Signed-off-by: Louis Kotze <loukot@gmail.com>
Link: https://patch.msgid.link/20260722070734.3612581-2-loukot@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
committed by
Johannes Berg
parent
f153501041
commit
a37286345f
@@ -8424,6 +8424,8 @@ cfg80211_inform_bss(struct wiphy *wiphy,
|
||||
* @bss_type: type of BSS, see &enum ieee80211_bss_type
|
||||
* @privacy: privacy filter, see &enum ieee80211_privacy
|
||||
* @use_for: indicates which use is intended
|
||||
* @extack: (optional) extack that is filled with the reason when no
|
||||
* usable entry was found; may be %NULL
|
||||
*
|
||||
* Return: Reference-counted BSS on success. %NULL on error.
|
||||
*/
|
||||
@@ -8433,7 +8435,8 @@ struct cfg80211_bss *__cfg80211_get_bss(struct wiphy *wiphy,
|
||||
const u8 *ssid, size_t ssid_len,
|
||||
enum ieee80211_bss_type bss_type,
|
||||
enum ieee80211_privacy privacy,
|
||||
u32 use_for);
|
||||
u32 use_for,
|
||||
struct netlink_ext_ack *extack);
|
||||
|
||||
/**
|
||||
* cfg80211_get_bss - get a BSS reference
|
||||
@@ -8457,7 +8460,7 @@ cfg80211_get_bss(struct wiphy *wiphy, struct ieee80211_channel *channel,
|
||||
{
|
||||
return __cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len,
|
||||
bss_type, privacy,
|
||||
NL80211_BSS_USE_FOR_NORMAL);
|
||||
NL80211_BSS_USE_FOR_NORMAL, NULL);
|
||||
}
|
||||
|
||||
static inline struct cfg80211_bss *
|
||||
|
||||
@@ -12890,9 +12890,11 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
|
||||
IEEE80211_BSS_TYPE_ESS,
|
||||
IEEE80211_PRIVACY_ANY);
|
||||
req.bss = __cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
|
||||
IEEE80211_BSS_TYPE_ESS,
|
||||
IEEE80211_PRIVACY_ANY,
|
||||
NL80211_BSS_USE_FOR_NORMAL,
|
||||
info->extack);
|
||||
if (!req.bss)
|
||||
return -ENOENT;
|
||||
|
||||
@@ -13037,6 +13039,7 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
|
||||
}
|
||||
|
||||
static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device *rdev,
|
||||
struct genl_info *info,
|
||||
const u8 *ssid, int ssid_len,
|
||||
struct nlattr **attrs,
|
||||
int assoc_link_id, int link_id)
|
||||
@@ -13046,8 +13049,10 @@ static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device
|
||||
const u8 *bssid;
|
||||
u32 freq, use_for = 0;
|
||||
|
||||
if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_WIPHY_FREQ])
|
||||
if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_WIPHY_FREQ]) {
|
||||
GENL_SET_ERR_MSG(info, "BSSID or frequency missing");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
bssid = nla_data(attrs[NL80211_ATTR_MAC]);
|
||||
|
||||
@@ -13056,8 +13061,10 @@ static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device
|
||||
freq += nla_get_u32(attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
|
||||
|
||||
chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
|
||||
if (!chan)
|
||||
if (!chan) {
|
||||
GENL_SET_ERR_MSG(info, "invalid or disabled channel");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (assoc_link_id >= 0)
|
||||
use_for = NL80211_BSS_USE_FOR_MLD_LINK;
|
||||
@@ -13068,7 +13075,7 @@ static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device
|
||||
ssid, ssid_len,
|
||||
IEEE80211_BSS_TYPE_ESS,
|
||||
IEEE80211_PRIVACY_ANY,
|
||||
use_for);
|
||||
use_for, info->extack);
|
||||
if (!bss)
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
@@ -13107,13 +13114,13 @@ static int nl80211_process_links(struct cfg80211_registered_device *rdev,
|
||||
return -EINVAL;
|
||||
}
|
||||
links[link_id].bss =
|
||||
nl80211_assoc_bss(rdev, ssid, ssid_len, attrs,
|
||||
nl80211_assoc_bss(rdev, info, ssid, ssid_len, attrs,
|
||||
assoc_link_id, link_id);
|
||||
if (IS_ERR(links[link_id].bss)) {
|
||||
err = PTR_ERR(links[link_id].bss);
|
||||
links[link_id].bss = NULL;
|
||||
NL_SET_ERR_MSG_ATTR(info->extack, link,
|
||||
"Error fetching BSS for link");
|
||||
/* the BSS lookup set the specific message already */
|
||||
NL_SET_BAD_ATTR(info->extack, link);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -13329,7 +13336,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
|
||||
if (req.link_id >= 0)
|
||||
return -EINVAL;
|
||||
|
||||
req.bss = nl80211_assoc_bss(rdev, ssid, ssid_len, info->attrs,
|
||||
req.bss = nl80211_assoc_bss(rdev, info, ssid, ssid_len, info->attrs,
|
||||
-1, -1);
|
||||
if (IS_ERR(req.bss))
|
||||
return PTR_ERR(req.bss);
|
||||
|
||||
@@ -1609,10 +1609,12 @@ struct cfg80211_bss *__cfg80211_get_bss(struct wiphy *wiphy,
|
||||
const u8 *ssid, size_t ssid_len,
|
||||
enum ieee80211_bss_type bss_type,
|
||||
enum ieee80211_privacy privacy,
|
||||
u32 use_for)
|
||||
u32 use_for,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
struct cfg80211_internal_bss *bss, *res = NULL;
|
||||
bool expired = false, unusable = false;
|
||||
unsigned long now = jiffies;
|
||||
int bss_privacy;
|
||||
|
||||
@@ -1634,22 +1636,48 @@ struct cfg80211_bss *__cfg80211_get_bss(struct wiphy *wiphy,
|
||||
continue;
|
||||
if (!is_valid_ether_addr(bss->pub.bssid))
|
||||
continue;
|
||||
if ((bss->pub.use_for & use_for) != use_for)
|
||||
if (!is_bss(&bss->pub, bssid, ssid, ssid_len))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* The identity checks above must all come first so that
|
||||
* the expired/unusable classification below only ever
|
||||
* applies to entries that actually match the request.
|
||||
*/
|
||||
|
||||
/* Don't get expired BSS structs */
|
||||
if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) &&
|
||||
!atomic_read(&bss->hold))
|
||||
!atomic_read(&bss->hold)) {
|
||||
expired = true;
|
||||
continue;
|
||||
if (is_bss(&bss->pub, bssid, ssid, ssid_len)) {
|
||||
res = bss;
|
||||
bss_ref_get(rdev, res);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((bss->pub.use_for & use_for) != use_for) {
|
||||
unusable = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
res = bss;
|
||||
bss_ref_get(rdev, res);
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&rdev->bss_lock);
|
||||
if (!res)
|
||||
if (!res) {
|
||||
if (expired && unusable)
|
||||
NL_SET_ERR_MSG(extack,
|
||||
"BSS entries are expired or cannot be used for the requested operation");
|
||||
else if (unusable)
|
||||
NL_SET_ERR_MSG(extack,
|
||||
"BSS cannot be used for the requested operation");
|
||||
else if (expired)
|
||||
NL_SET_ERR_MSG(extack,
|
||||
"BSS entry in scan results is expired");
|
||||
else
|
||||
NL_SET_ERR_MSG(extack,
|
||||
"BSS not found in scan results");
|
||||
return NULL;
|
||||
}
|
||||
trace_cfg80211_return_bss(&res->pub);
|
||||
return &res->pub;
|
||||
}
|
||||
|
||||
@@ -617,7 +617,7 @@ static void test_inform_bss_ml_sta(struct kunit *test)
|
||||
link_bss = __cfg80211_get_bss(wiphy, NULL, sta_prof.bssid, NULL, 0,
|
||||
IEEE80211_BSS_TYPE_ANY,
|
||||
IEEE80211_PRIVACY_ANY,
|
||||
0);
|
||||
0, NULL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, link_bss);
|
||||
KUNIT_EXPECT_EQ(test, link_bss->signal, 0);
|
||||
KUNIT_EXPECT_EQ(test, link_bss->beacon_interval,
|
||||
|
||||
Reference in New Issue
Block a user