@@ -11114,12 +11114,83 @@ static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device
1111411114 return bss;
1111511115}
1111611116
11117+ static int nl80211_process_links(struct cfg80211_registered_device *rdev,
11118+ struct cfg80211_assoc_link *links,
11119+ const u8 *ssid, int ssid_len,
11120+ struct genl_info *info)
11121+ {
11122+ unsigned int attrsize = NUM_NL80211_ATTR * sizeof(struct nlattr *);
11123+ struct nlattr **attrs __free(kfree) = kzalloc(attrsize, GFP_KERNEL);
11124+ struct nlattr *link;
11125+ unsigned int link_id;
11126+ int rem, err;
11127+
11128+ if (!attrs)
11129+ return -ENOMEM;
11130+
11131+ nla_for_each_nested(link, info->attrs[NL80211_ATTR_MLO_LINKS], rem) {
11132+ memset(attrs, 0, attrsize);
11133+
11134+ nla_parse_nested(attrs, NL80211_ATTR_MAX, link, NULL, NULL);
11135+
11136+ if (!attrs[NL80211_ATTR_MLO_LINK_ID]) {
11137+ NL_SET_BAD_ATTR(info->extack, link);
11138+ return -EINVAL;
11139+ }
11140+
11141+ link_id = nla_get_u8(attrs[NL80211_ATTR_MLO_LINK_ID]);
11142+ /* cannot use the same link ID again */
11143+ if (links[link_id].bss) {
11144+ NL_SET_BAD_ATTR(info->extack, link);
11145+ return -EINVAL;
11146+ }
11147+ links[link_id].bss =
11148+ nl80211_assoc_bss(rdev, ssid, ssid_len, attrs,
11149+ link_id, link_id);
11150+ if (IS_ERR(links[link_id].bss)) {
11151+ err = PTR_ERR(links[link_id].bss);
11152+ links[link_id].bss = NULL;
11153+ NL_SET_ERR_MSG_ATTR(info->extack, link,
11154+ "Error fetching BSS for link");
11155+ return err;
11156+ }
11157+
11158+ if (attrs[NL80211_ATTR_IE]) {
11159+ links[link_id].elems = nla_data(attrs[NL80211_ATTR_IE]);
11160+ links[link_id].elems_len =
11161+ nla_len(attrs[NL80211_ATTR_IE]);
11162+
11163+ if (cfg80211_find_elem(WLAN_EID_FRAGMENT,
11164+ links[link_id].elems,
11165+ links[link_id].elems_len)) {
11166+ NL_SET_ERR_MSG_ATTR(info->extack,
11167+ attrs[NL80211_ATTR_IE],
11168+ "cannot deal with fragmentation");
11169+ return -EINVAL;
11170+ }
11171+
11172+ if (cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
11173+ links[link_id].elems,
11174+ links[link_id].elems_len)) {
11175+ NL_SET_ERR_MSG_ATTR(info->extack,
11176+ attrs[NL80211_ATTR_IE],
11177+ "cannot deal with non-inheritance");
11178+ return -EINVAL;
11179+ }
11180+ }
11181+
11182+ links[link_id].disabled =
11183+ nla_get_flag(attrs[NL80211_ATTR_MLO_LINK_DISABLED]);
11184+ }
11185+
11186+ return 0;
11187+ }
11188+
1111711189static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
1111811190{
1111911191 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1112011192 struct net_device *dev = info->user_ptr[1];
1112111193 struct cfg80211_assoc_request req = {};
11122- struct nlattr **attrs = NULL;
1112311194 const u8 *ap_addr, *ssid;
1112411195 unsigned int link_id;
1112511196 int err, ssid_len;
@@ -11258,10 +11329,6 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
1125811329 req.link_id = nl80211_link_id_or_invalid(info->attrs);
1125911330
1126011331 if (info->attrs[NL80211_ATTR_MLO_LINKS]) {
11261- unsigned int attrsize = NUM_NL80211_ATTR * sizeof(*attrs);
11262- struct nlattr *link;
11263- int rem = 0;
11264-
1126511332 if (req.link_id < 0)
1126611333 return -EINVAL;
1126711334
@@ -11276,72 +11343,10 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
1127611343 req.ap_mld_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
1127711344 ap_addr = req.ap_mld_addr;
1127811345
11279- attrs = kzalloc(attrsize, GFP_KERNEL);
11280- if (!attrs)
11281- return -ENOMEM;
11282-
11283- nla_for_each_nested(link,
11284- info->attrs[NL80211_ATTR_MLO_LINKS],
11285- rem) {
11286- memset(attrs, 0, attrsize);
11287-
11288- nla_parse_nested(attrs, NL80211_ATTR_MAX,
11289- link, NULL, NULL);
11290-
11291- if (!attrs[NL80211_ATTR_MLO_LINK_ID]) {
11292- err = -EINVAL;
11293- NL_SET_BAD_ATTR(info->extack, link);
11294- goto free;
11295- }
11296-
11297- link_id = nla_get_u8(attrs[NL80211_ATTR_MLO_LINK_ID]);
11298- /* cannot use the same link ID again */
11299- if (req.links[link_id].bss) {
11300- err = -EINVAL;
11301- NL_SET_BAD_ATTR(info->extack, link);
11302- goto free;
11303- }
11304- req.links[link_id].bss =
11305- nl80211_assoc_bss(rdev, ssid, ssid_len, attrs,
11306- req.link_id, link_id);
11307- if (IS_ERR(req.links[link_id].bss)) {
11308- err = PTR_ERR(req.links[link_id].bss);
11309- req.links[link_id].bss = NULL;
11310- NL_SET_ERR_MSG_ATTR(info->extack,
11311- link, "Error fetching BSS for link");
11312- goto free;
11313- }
11314-
11315- if (attrs[NL80211_ATTR_IE]) {
11316- req.links[link_id].elems =
11317- nla_data(attrs[NL80211_ATTR_IE]);
11318- req.links[link_id].elems_len =
11319- nla_len(attrs[NL80211_ATTR_IE]);
11320-
11321- if (cfg80211_find_elem(WLAN_EID_FRAGMENT,
11322- req.links[link_id].elems,
11323- req.links[link_id].elems_len)) {
11324- NL_SET_ERR_MSG_ATTR(info->extack,
11325- attrs[NL80211_ATTR_IE],
11326- "cannot deal with fragmentation");
11327- err = -EINVAL;
11328- goto free;
11329- }
11330-
11331- if (cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
11332- req.links[link_id].elems,
11333- req.links[link_id].elems_len)) {
11334- NL_SET_ERR_MSG_ATTR(info->extack,
11335- attrs[NL80211_ATTR_IE],
11336- "cannot deal with non-inheritance");
11337- err = -EINVAL;
11338- goto free;
11339- }
11340- }
11341-
11342- req.links[link_id].disabled =
11343- nla_get_flag(attrs[NL80211_ATTR_MLO_LINK_DISABLED]);
11344- }
11346+ err = nl80211_process_links(rdev, req.links, ssid, ssid_len,
11347+ info);
11348+ if (err)
11349+ goto free;
1134511350
1134611351 if (!req.links[req.link_id].bss) {
1134711352 err = -EINVAL;
@@ -11361,9 +11366,6 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
1136111366 err = -EINVAL;
1136211367 goto free;
1136311368 }
11364-
11365- kfree(attrs);
11366- attrs = NULL;
1136711369 } else {
1136811370 if (req.link_id >= 0)
1136911371 return -EINVAL;
@@ -11423,7 +11425,6 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
1142311425 for (link_id = 0; link_id < ARRAY_SIZE(req.links); link_id++)
1142411426 cfg80211_put_bss(&rdev->wiphy, req.links[link_id].bss);
1142511427 cfg80211_put_bss(&rdev->wiphy, req.bss);
11426- kfree(attrs);
1142711428
1142811429 return err;
1142911430}
0 commit comments