diff options
| -rw-r--r-- | include/net/cfg80211.h | 8 | ||||
| -rw-r--r-- | include/uapi/linux/nl80211.h | 9 | ||||
| -rw-r--r-- | net/wireless/nl80211.c | 46 |
3 files changed, 63 insertions, 0 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 45f6bf591104..5db5fe24eff6 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
| @@ -744,6 +744,10 @@ enum station_parameters_apply_mask { | |||
| 744 | * @capability: station capability | 744 | * @capability: station capability |
| 745 | * @ext_capab: extended capabilities of the station | 745 | * @ext_capab: extended capabilities of the station |
| 746 | * @ext_capab_len: number of extended capabilities | 746 | * @ext_capab_len: number of extended capabilities |
| 747 | * @supported_channels: supported channels in IEEE 802.11 format | ||
| 748 | * @supported_channels_len: number of supported channels | ||
| 749 | * @supported_oper_classes: supported oper classes in IEEE 802.11 format | ||
| 750 | * @supported_oper_classes_len: number of supported operating classes | ||
| 747 | */ | 751 | */ |
| 748 | struct station_parameters { | 752 | struct station_parameters { |
| 749 | const u8 *supported_rates; | 753 | const u8 *supported_rates; |
| @@ -763,6 +767,10 @@ struct station_parameters { | |||
| 763 | u16 capability; | 767 | u16 capability; |
| 764 | const u8 *ext_capab; | 768 | const u8 *ext_capab; |
| 765 | u8 ext_capab_len; | 769 | u8 ext_capab_len; |
| 770 | const u8 *supported_channels; | ||
| 771 | u8 supported_channels_len; | ||
| 772 | const u8 *supported_oper_classes; | ||
| 773 | u8 supported_oper_classes_len; | ||
| 766 | }; | 774 | }; |
| 767 | 775 | ||
| 768 | /** | 776 | /** |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 8c0417c222c6..f2aef2a7a570 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
| @@ -1496,6 +1496,11 @@ enum nl80211_commands { | |||
| 1496 | * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32. | 1496 | * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32. |
| 1497 | * As specified in the &enum nl80211_rxmgmt_flags. | 1497 | * As specified in the &enum nl80211_rxmgmt_flags. |
| 1498 | * | 1498 | * |
| 1499 | * @NL80211_ATTR_STA_SUPPORTED_CHANNELS: array of supported channels. | ||
| 1500 | * | ||
| 1501 | * @NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES: array of supported | ||
| 1502 | * supported operating classes. | ||
| 1503 | * | ||
| 1499 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 1504 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
| 1500 | * @__NL80211_ATTR_AFTER_LAST: internal use | 1505 | * @__NL80211_ATTR_AFTER_LAST: internal use |
| 1501 | */ | 1506 | */ |
| @@ -1806,6 +1811,10 @@ enum nl80211_attrs { | |||
| 1806 | 1811 | ||
| 1807 | NL80211_ATTR_RXMGMT_FLAGS, | 1812 | NL80211_ATTR_RXMGMT_FLAGS, |
| 1808 | 1813 | ||
| 1814 | NL80211_ATTR_STA_SUPPORTED_CHANNELS, | ||
| 1815 | |||
| 1816 | NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES, | ||
| 1817 | |||
| 1809 | /* add attributes here, update the policy in nl80211.c */ | 1818 | /* add attributes here, update the policy in nl80211.c */ |
| 1810 | 1819 | ||
| 1811 | __NL80211_ATTR_AFTER_LAST, | 1820 | __NL80211_ATTR_AFTER_LAST, |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 2838206ddad3..460638ac2d73 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -354,6 +354,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
| 354 | [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED }, | 354 | [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED }, |
| 355 | [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 }, | 355 | [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 }, |
| 356 | [NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 }, | 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 | /* policy for the key attributes */ | 361 | /* policy for the key attributes */ |
| @@ -3896,9 +3898,45 @@ static int nl80211_parse_sta_wme(struct genl_info *info, | |||
| 3896 | return 0; | 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 | static int nl80211_set_station_tdls(struct genl_info *info, | 3936 | static int nl80211_set_station_tdls(struct genl_info *info, |
| 3900 | struct station_parameters *params) | 3937 | struct station_parameters *params) |
| 3901 | { | 3938 | { |
| 3939 | int err; | ||
| 3902 | /* Dummy STA entry gets updated once the peer capabilities are known */ | 3940 | /* Dummy STA entry gets updated once the peer capabilities are known */ |
| 3903 | if (info->attrs[NL80211_ATTR_PEER_AID]) | 3941 | if (info->attrs[NL80211_ATTR_PEER_AID]) |
| 3904 | params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); | 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, | |||
| 3909 | params->vht_capa = | 3947 | params->vht_capa = |
| 3910 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); | 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 | return nl80211_parse_sta_wme(info, params); | 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) | |||
| 4089 | return -EINVAL; | 4131 | return -EINVAL; |
| 4090 | } | 4132 | } |
| 4091 | 4133 | ||
| 4134 | err = nl80211_parse_sta_channel_info(info, ¶ms); | ||
| 4135 | if (err) | ||
| 4136 | return err; | ||
| 4137 | |||
| 4092 | err = nl80211_parse_sta_wme(info, ¶ms); | 4138 | err = nl80211_parse_sta_wme(info, ¶ms); |
| 4093 | if (err) | 4139 | if (err) |
| 4094 | return err; | 4140 | return err; |
