Skip to content

Commit

Permalink
wifi: cfg80211: report per-link errors during association
Browse files Browse the repository at this point in the history
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: Benjamin Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
Link: https://lore.kernel.org/r/20230920211508.ebe63c0bd513.I40799998f02bf987acee1501a2522dc98bb6eb5a@changeid
Signed-off-by: Johannes Berg <[email protected]>
  • Loading branch information
benzea authored and jmberg-intel committed Sep 25, 2023
1 parent ef246a1 commit a7b2cc5
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 6 deletions.
3 changes: 3 additions & 0 deletions include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

/**
Expand Down
50 changes: 44 additions & 6 deletions net/wireless/nl80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -11067,20 +11068,24 @@ 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;
}

link_id = nla_get_u8(attrs[NL80211_ATTR_MLO_LINK_ID]);
/* 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 =
nl80211_assoc_bss(rdev, ssid, ssid_len, attrs);
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;
}

Expand All @@ -11093,17 +11098,19 @@ 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;
}

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;
}
Expand Down Expand Up @@ -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]) {
Expand All @@ -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:
Expand Down

0 comments on commit a7b2cc5

Please sign in to comment.