@@ -11114,12 +11114,83 @@ static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device
11114
11114
return bss;
11115
11115
}
11116
11116
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
+
11117
11189
static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
11118
11190
{
11119
11191
struct cfg80211_registered_device *rdev = info->user_ptr[0];
11120
11192
struct net_device *dev = info->user_ptr[1];
11121
11193
struct cfg80211_assoc_request req = {};
11122
- struct nlattr **attrs = NULL;
11123
11194
const u8 *ap_addr, *ssid;
11124
11195
unsigned int link_id;
11125
11196
int err, ssid_len;
@@ -11258,10 +11329,6 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
11258
11329
req.link_id = nl80211_link_id_or_invalid(info->attrs);
11259
11330
11260
11331
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
-
11265
11332
if (req.link_id < 0)
11266
11333
return -EINVAL;
11267
11334
@@ -11276,72 +11343,10 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
11276
11343
req.ap_mld_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
11277
11344
ap_addr = req.ap_mld_addr;
11278
11345
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;
11345
11350
11346
11351
if (!req.links[req.link_id].bss) {
11347
11352
err = -EINVAL;
@@ -11361,9 +11366,6 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
11361
11366
err = -EINVAL;
11362
11367
goto free;
11363
11368
}
11364
-
11365
- kfree(attrs);
11366
- attrs = NULL;
11367
11369
} else {
11368
11370
if (req.link_id >= 0)
11369
11371
return -EINVAL;
@@ -11423,7 +11425,6 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
11423
11425
for (link_id = 0; link_id < ARRAY_SIZE(req.links); link_id++)
11424
11426
cfg80211_put_bss(&rdev->wiphy, req.links[link_id].bss);
11425
11427
cfg80211_put_bss(&rdev->wiphy, req.bss);
11426
- kfree(attrs);
11427
11428
11428
11429
return err;
11429
11430
}
0 commit comments