Commit a7b2cc59 authored by Benjamin Berg's avatar Benjamin Berg Committed by Johannes Berg

wifi: cfg80211: report per-link errors during association

When one of the links (other than the assoc_link) is misconfigured
and cannot work the association will fail. However, userspace was not
able to tell that the operation only failed because of a problem with
one of the links. Fix this, by allowing the driver to set a per-link
error code and reporting the (first) offending link by setting the
bad_attr accordingly.

This only allows us to report the first error, but that is sufficient
for userspace to e.g. remove the offending link and retry.
Signed-off-by: default avatarBenjamin Berg <benjamin.berg@intel.com>
Signed-off-by: default avatarGregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230920211508.ebe63c0bd513.I40799998f02bf987acee1501a2522dc98bb6eb5a@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent ef246a14
......@@ -2980,12 +2980,15 @@ struct cfg80211_auth_request {
* @elems_len: length of the elements
* @disabled: If set this link should be included during association etc. but it
* should not be used until enabled by the AP MLD.
* @error: per-link error code, must be <= 0. If there is an error, then the
* operation as a whole must fail.
*/
struct cfg80211_assoc_link {
struct cfg80211_bss *bss;
const u8 *elems;
size_t elems_len;
bool disabled;
int error;
};
/**
......
......@@ -10941,8 +10941,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
if (cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
req.ie, req.ie_len)) {
GENL_SET_ERR_MSG(info,
"non-inheritance makes no sense");
NL_SET_ERR_MSG_ATTR(info->extack,
info->attrs[NL80211_ATTR_IE],
"non-inheritance makes no sense");
return -EINVAL;
}
}
......@@ -11067,6 +11068,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
if (!attrs[NL80211_ATTR_MLO_LINK_ID]) {
err = -EINVAL;
NL_SET_BAD_ATTR(info->extack, link);
goto free;
}
......@@ -11074,6 +11076,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
/* cannot use the same link ID again */
if (req.links[link_id].bss) {
err = -EINVAL;
NL_SET_BAD_ATTR(info->extack, link);
goto free;
}
req.links[link_id].bss =
......@@ -11081,6 +11084,8 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
if (IS_ERR(req.links[link_id].bss)) {
err = PTR_ERR(req.links[link_id].bss);
req.links[link_id].bss = NULL;
NL_SET_ERR_MSG_ATTR(info->extack,
link, "Error fetching BSS for link");
goto free;
}
......@@ -11093,8 +11098,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
if (cfg80211_find_elem(WLAN_EID_FRAGMENT,
req.links[link_id].elems,
req.links[link_id].elems_len)) {
GENL_SET_ERR_MSG(info,
"cannot deal with fragmentation");
NL_SET_ERR_MSG_ATTR(info->extack,
attrs[NL80211_ATTR_IE],
"cannot deal with fragmentation");
err = -EINVAL;
goto free;
}
......@@ -11102,8 +11108,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
if (cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
req.links[link_id].elems,
req.links[link_id].elems_len)) {
GENL_SET_ERR_MSG(info,
"cannot deal with non-inheritance");
NL_SET_ERR_MSG_ATTR(info->extack,
attrs[NL80211_ATTR_IE],
"cannot deal with non-inheritance");
err = -EINVAL;
goto free;
}
......@@ -11146,6 +11153,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
if (!err) {
struct nlattr *link;
int rem = 0;
err = cfg80211_mlme_assoc(rdev, dev, &req);
if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
......@@ -11154,6 +11164,34 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
memcpy(dev->ieee80211_ptr->disconnect_bssid,
ap_addr, ETH_ALEN);
}
/* Report error from first problematic link */
if (info->attrs[NL80211_ATTR_MLO_LINKS]) {
nla_for_each_nested(link,
info->attrs[NL80211_ATTR_MLO_LINKS],
rem) {
struct nlattr *link_id_attr =
nla_find_nested(link, NL80211_ATTR_MLO_LINK_ID);
if (!link_id_attr)
continue;
link_id = nla_get_u8(link_id_attr);
if (link_id == req.link_id)
continue;
if (!req.links[link_id].error ||
WARN_ON(req.links[link_id].error > 0))
continue;
WARN_ON(err >= 0);
NL_SET_BAD_ATTR(info->extack, link);
err = req.links[link_id].error;
break;
}
}
}
free:
......
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