| @@ -354,6 +354,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { · 353 unmodified lines |
| 354 | 354 | [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED }, |
| 355 | 355 | [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 }, |
| 356 | 356 | [NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 }, |
| 357 | + [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY }, |
| 358 | + [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY }, |
| 357 | 359 | }; |
| 358 | 360 | |
| 359 | 361 | /* policy for the key attributes */ |
| @@ -3896,9 +3898,45 @@ static int nl80211_parse_sta_wme(struct genl_info *info, · 3536 unmodified lines |
| 3896 | 3898 | return 0; |
| 3897 | 3899 | } |
| 3898 | 3900 | |
| 3901 | +static int nl80211_parse_sta_channel_info(struct genl_info *info, |
| 3902 | + struct station_parameters *params) |
| 3903 | +{ |
| 3904 | + if (info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]) { |
| 3905 | + params->supported_channels = |
| 3906 | + nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]); |
| 3907 | + params->supported_channels_len = |
| 3908 | + nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]); |
| 3909 | + /* |
| 3910 | + * Need to include at least one (first channel, number of |
| 3911 | + * channels) tuple for each subband, and must have proper |
| 3912 | + * tuples for the rest of the data as well. |
| 3913 | + */ |
| 3914 | + if (params->supported_channels_len < 2) |
| 3915 | + return -EINVAL; |
| 3916 | + if (params->supported_channels_len % 2) |
| 3917 | + return -EINVAL; |
| 3918 | + } |
| 3919 | + |
| 3920 | + if (info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]) { |
| 3921 | + params->supported_oper_classes = |
| 3922 | + nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]); |
| 3923 | + params->supported_oper_classes_len = |
| 3924 | + nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]); |
| 3925 | + /* |
| 3926 | + * The value of the Length field of the Supported Operating |
| 3927 | + * Classes element is between 2 and 253. |
| 3928 | + */ |
| 3929 | + if (params->supported_oper_classes_len < 2 || |
| 3930 | + params->supported_oper_classes_len > 253) |
| 3931 | + return -EINVAL; |
| 3932 | + } |
| 3933 | + return 0; |
| 3934 | +} |
| 3935 | + |
| 3899 | 3936 | static int nl80211_set_station_tdls(struct genl_info *info, |
| 3900 | 3937 | struct station_parameters *params) |
| 3901 | 3938 | { |
| 3939 | + int err; |
| 3902 | 3940 | /* Dummy STA entry gets updated once the peer capabilities are known */ |
| 3903 | 3941 | if (info->attrs[NL80211_ATTR_PEER_AID]) |
| 3904 | 3942 | params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); |
| @@ -3909,6 +3947,10 @@ static int nl80211_set_station_tdls(struct genl_info *info, · 4 unmodified lines |
| 3909 | 3947 | params->vht_capa = |
| 3910 | 3948 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); |
| 3911 | 3949 | |
| 3950 | + err = nl80211_parse_sta_channel_info(info, params); |
| 3951 | + if (err) |
| 3952 | + return err; |
| 3953 | + |
| 3912 | 3954 | return nl80211_parse_sta_wme(info, params); |
| 3913 | 3955 | } |
| 3914 | 3956 | |
| @@ -4089,6 +4131,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) · 174 unmodified lines |
| 4089 | 4131 | return -EINVAL; |
| 4090 | 4132 | } |
| 4091 | 4133 | |
| 4134 | + err = nl80211_parse_sta_channel_info(info, ¶ms); |
| 4135 | + if (err) |
| 4136 | + return err; |
| 4137 | + |
| 4092 | 4138 | err = nl80211_parse_sta_wme(info, ¶ms); |
| 4093 | 4139 | if (err) |
| 4094 | 4140 | return err; |