aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSunil Dutt <c_duttus@qti.qualcomm.com>2013-10-09 11:15:21 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-10-11 09:26:58 -0400
commitc01fc9ada926aaad907989ca2eba40c2a2a73afe (patch)
treea63aa4a69475d7fe5265927d834c8b0fcd6eb493
parent789fd03331aa1ec45cb58168e2d82525c97c7351 (diff)
cfg80211: pass station supported channel and oper class info
The information of the peer's supported channels and supported operating classes are required for the driver to perform TDLS off channel operations. This commit enhances the function nl80211_(new)set_station to pass this information of the peer to the driver. Signed-off-by: Sunil Dutt <c_duttus@qti.qualcomm.com> [return errors for malformed tuples] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-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;