aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/cfg80211.h8
-rw-r--r--include/uapi/linux/nl80211.h9
-rw-r--r--net/wireless/nl80211.c46
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 */
748struct station_parameters { 752struct 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
3901static 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
3899static int nl80211_set_station_tdls(struct genl_info *info, 3936static 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, &params);
4135 if (err)
4136 return err;
4137
4092 err = nl80211_parse_sta_wme(info, &params); 4138 err = nl80211_parse_sta_wme(info, &params);
4093 if (err) 4139 if (err)
4094 return err; 4140 return err;