| @@ -809,6 +809,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 808 unmodified lines |
| 809 | 809 | |
| 810 | 810 | [NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS] = { .type = NLA_U16 }, |
| 811 | 811 | [NL80211_ATTR_HW_TIMESTAMP_ENABLED] = { .type = NLA_FLAG }, |
| 812 | + [NL80211_ATTR_EMA_RNR_ELEMS] = { .type = NLA_NESTED }, |
| 812 | 813 | }; |
| 813 | 814 | |
| 814 | 815 | /* policy for the key attributes */ |
| @@ -5425,6 +5426,38 @@ nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs) · 4610 unmodified lines |
| 5425 | 5426 | return elems; |
| 5426 | 5427 | } |
| 5427 | 5428 | |
| 5429 | +static struct cfg80211_rnr_elems * |
| 5430 | +nl80211_parse_rnr_elems(struct wiphy *wiphy, struct nlattr *attrs, |
| 5431 | + struct netlink_ext_ack *extack) |
| 5432 | +{ |
| 5433 | + struct nlattr *nl_elems; |
| 5434 | + struct cfg80211_rnr_elems *elems; |
| 5435 | + int rem_elems; |
| 5436 | + u8 i = 0, num_elems = 0; |
| 5437 | + |
| 5438 | + nla_for_each_nested(nl_elems, attrs, rem_elems) { |
| 5439 | + int ret; |
| 5440 | + |
| 5441 | + ret = validate_ie_attr(nl_elems, extack); |
| 5442 | + if (ret) |
| 5443 | + return ERR_PTR(ret); |
| 5444 | + |
| 5445 | + num_elems++; |
| 5446 | + } |
| 5447 | + |
| 5448 | + elems = kzalloc(struct_size(elems, elem, num_elems), GFP_KERNEL); |
| 5449 | + if (!elems) |
| 5450 | + return ERR_PTR(-ENOMEM); |
| 5451 | + |
| 5452 | + nla_for_each_nested(nl_elems, attrs, rem_elems) { |
| 5453 | + elems->elem[i].data = nla_data(nl_elems); |
| 5454 | + elems->elem[i].len = nla_len(nl_elems); |
| 5455 | + i++; |
| 5456 | + } |
| 5457 | + elems->cnt = num_elems; |
| 5458 | + return elems; |
| 5459 | +} |
| 5460 | + |
| 5428 | 5461 | static int nl80211_parse_he_bss_color(struct nlattr *attrs, |
| 5429 | 5462 | struct cfg80211_he_bss_color *he_bss_color) |
| 5430 | 5463 | { |
| @@ -5451,7 +5484,8 @@ static int nl80211_parse_he_bss_color(struct nlattr *attrs, · 20 unmodified lines |
| 5451 | 5484 | |
| 5452 | 5485 | static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, |
| 5453 | 5486 | struct nlattr *attrs[], |
| 5454 | | − struct cfg80211_beacon_data *bcn) |
| 5487 | + struct cfg80211_beacon_data *bcn, |
| 5488 | + struct netlink_ext_ack *extack) |
| 5455 | 5489 | { |
| 5456 | 5490 | bool haveinfo = false; |
| 5457 | 5491 | int err; |
| @@ -5548,6 +5582,21 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, · 90 unmodified lines |
| 5548 | 5582 | return PTR_ERR(mbssid); |
| 5549 | 5583 | |
| 5550 | 5584 | bcn->mbssid_ies = mbssid; |
| 5585 | + |
| 5586 | + if (bcn->mbssid_ies && attrs[NL80211_ATTR_EMA_RNR_ELEMS]) { |
| 5587 | + struct cfg80211_rnr_elems *rnr = |
| 5588 | + nl80211_parse_rnr_elems(&rdev->wiphy, |
| 5589 | + attrs[NL80211_ATTR_EMA_RNR_ELEMS], |
| 5590 | + extack); |
| 5591 | + |
| 5592 | + if (IS_ERR(rnr)) |
| 5593 | + return PTR_ERR(rnr); |
| 5594 | + |
| 5595 | + if (rnr && rnr->cnt < bcn->mbssid_ies->cnt) |
| 5596 | + return -EINVAL; |
| 5597 | + |
| 5598 | + bcn->rnr_ies = rnr; |
| 5599 | + } |
| 5551 | 5600 | } |
| 5552 | 5601 | |
| 5553 | 5602 | return 0; |
| @@ -5866,7 +5915,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) · 312 unmodified lines |
| 5866 | 5915 | if (!params) |
| 5867 | 5916 | return -ENOMEM; |
| 5868 | 5917 | |
| 5869 | | − err = nl80211_parse_beacon(rdev, info->attrs, ¶ms->beacon); |
| 5918 | + err = nl80211_parse_beacon(rdev, info->attrs, ¶ms->beacon, |
| 5919 | + info->extack); |
| 5870 | 5920 | if (err) |
| 5871 | 5921 | goto out; |
| 5872 | 5922 | |
| @@ -6096,6 +6146,11 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) · 223 unmodified lines |
| 6096 | 6146 | goto out_unlock; |
| 6097 | 6147 | } |
| 6098 | 6148 | |
| 6149 | + if (!params->mbssid_config.ema && params->beacon.rnr_ies) { |
| 6150 | + err = -EINVAL; |
| 6151 | + goto out_unlock; |
| 6152 | + } |
| 6153 | + |
| 6099 | 6154 | err = nl80211_calculate_ap_params(params); |
| 6100 | 6155 | if (err) |
| 6101 | 6156 | goto out_unlock; |
| @@ -6137,6 +6192,7 @@ out: · 35 unmodified lines |
| 6137 | 6192 | params->mbssid_config.tx_wdev->netdev && |
| 6138 | 6193 | params->mbssid_config.tx_wdev->netdev != dev) |
| 6139 | 6194 | dev_put(params->mbssid_config.tx_wdev->netdev); |
| 6195 | + kfree(params->beacon.rnr_ies); |
| 6140 | 6196 | kfree(params); |
| 6141 | 6197 | |
| 6142 | 6198 | return err; |
| @@ -6161,7 +6217,7 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info) · 18 unmodified lines |
| 6161 | 6217 | if (!wdev->links[link_id].ap.beacon_interval) |
| 6162 | 6218 | return -EINVAL; |
| 6163 | 6219 | |
| 6164 | | − err = nl80211_parse_beacon(rdev, info->attrs, ¶ms); |
| 6220 | + err = nl80211_parse_beacon(rdev, info->attrs, ¶ms, info->extack); |
| 6165 | 6221 | if (err) |
| 6166 | 6222 | goto out; |
| 6167 | 6223 | |
| @@ -6171,6 +6227,7 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info) · 3 unmodified lines |
| 6171 | 6227 | |
| 6172 | 6228 | out: |
| 6173 | 6229 | kfree(params.mbssid_ies); |
| 6230 | + kfree(params.rnr_ies); |
| 6174 | 6231 | return err; |
| 6175 | 6232 | } |
| 6176 | 6233 | |
| @@ -10030,7 +10087,8 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) · 3853 unmodified lines |
| 10030 | 10087 | if (!need_new_beacon) |
| 10031 | 10088 | goto skip_beacons; |
| 10032 | 10089 | |
| 10033 | | − err = nl80211_parse_beacon(rdev, info->attrs, ¶ms.beacon_after); |
| 10090 | + err = nl80211_parse_beacon(rdev, info->attrs, ¶ms.beacon_after, |
| 10091 | + info->extack); |
| 10034 | 10092 | if (err) |
| 10035 | 10093 | goto free; |
| 10036 | 10094 | |
| @@ -10047,7 +10105,8 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) · 10 unmodified lines |
| 10047 | 10105 | if (err) |
| 10048 | 10106 | goto free; |
| 10049 | 10107 | |
| 10050 | | − err = nl80211_parse_beacon(rdev, csa_attrs, ¶ms.beacon_csa); |
| 10108 | + err = nl80211_parse_beacon(rdev, csa_attrs, ¶ms.beacon_csa, |
| 10109 | + info->extack); |
| 10051 | 10110 | if (err) |
| 10052 | 10111 | goto free; |
| 10053 | 10112 | |
| @@ -10167,6 +10226,8 @@ skip_beacons: · 113 unmodified lines |
| 10167 | 10226 | free: |
| 10168 | 10227 | kfree(params.beacon_after.mbssid_ies); |
| 10169 | 10228 | kfree(params.beacon_csa.mbssid_ies); |
| 10229 | + kfree(params.beacon_after.rnr_ies); |
| 10230 | + kfree(params.beacon_csa.rnr_ies); |
| 10170 | 10231 | kfree(csa_attrs); |
| 10171 | 10232 | return err; |
| 10172 | 10233 | } |
| @@ -15882,7 +15943,8 @@ static int nl80211_color_change(struct sk_buff *skb, struct genl_info *info) · 5709 unmodified lines |
| 15882 | 15943 | params.count = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT]); |
| 15883 | 15944 | params.color = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR]); |
| 15884 | 15945 | |
| 15885 | | − err = nl80211_parse_beacon(rdev, info->attrs, ¶ms.beacon_next); |
| 15946 | + err = nl80211_parse_beacon(rdev, info->attrs, ¶ms.beacon_next, |
| 15947 | + info->extack); |
| 15886 | 15948 | if (err) |
| 15887 | 15949 | return err; |
| 15888 | 15950 | |
| @@ -15896,7 +15958,8 @@ static int nl80211_color_change(struct sk_buff *skb, struct genl_info *info) · 7 unmodified lines |
| 15896 | 15958 | if (err) |
| 15897 | 15959 | goto out; |
| 15898 | 15960 | |
| 15899 | | − err = nl80211_parse_beacon(rdev, tb, ¶ms.beacon_color_change); |
| 15961 | + err = nl80211_parse_beacon(rdev, tb, ¶ms.beacon_color_change, |
| 15962 | + info->extack); |
| 15900 | 15963 | if (err) |
| 15901 | 15964 | goto out; |
| 15902 | 15965 | |
| @@ -15952,6 +16015,8 @@ static int nl80211_color_change(struct sk_buff *skb, struct genl_info *info) · 49 unmodified lines |
| 15952 | 16015 | out: |
| 15953 | 16016 | kfree(params.beacon_next.mbssid_ies); |
| 15954 | 16017 | kfree(params.beacon_color_change.mbssid_ies); |
| 16018 | + kfree(params.beacon_next.rnr_ies); |
| 16019 | + kfree(params.beacon_color_change.rnr_ies); |
| 15955 | 16020 | kfree(tb); |
| 15956 | 16021 | return err; |
| 15957 | 16022 | } |