diff options
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 75 |
1 files changed, 70 insertions, 5 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 5e1d658a8b5a..e3e1494e769a 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -58,6 +58,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
58 | [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, | 58 | [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, |
59 | [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, | 59 | [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, |
60 | .len = BUS_ID_SIZE-1 }, | 60 | .len = BUS_ID_SIZE-1 }, |
61 | [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, | ||
61 | 62 | ||
62 | [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, | 63 | [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, |
63 | [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, | 64 | [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, |
@@ -95,6 +96,8 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
95 | [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 }, | 96 | [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 }, |
96 | [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 }, | 97 | [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 }, |
97 | [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 }, | 98 | [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 }, |
99 | [NL80211_ATTR_BSS_BASIC_RATES] = { .type = NLA_BINARY, | ||
100 | .len = NL80211_MAX_SUPP_RATES }, | ||
98 | 101 | ||
99 | [NL80211_ATTR_MESH_PARAMS] = { .type = NLA_NESTED }, | 102 | [NL80211_ATTR_MESH_PARAMS] = { .type = NLA_NESTED }, |
100 | 103 | ||
@@ -284,20 +287,76 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
284 | return -ENOBUFS; | 287 | return -ENOBUFS; |
285 | } | 288 | } |
286 | 289 | ||
290 | static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = { | ||
291 | [NL80211_TXQ_ATTR_QUEUE] = { .type = NLA_U8 }, | ||
292 | [NL80211_TXQ_ATTR_TXOP] = { .type = NLA_U16 }, | ||
293 | [NL80211_TXQ_ATTR_CWMIN] = { .type = NLA_U16 }, | ||
294 | [NL80211_TXQ_ATTR_CWMAX] = { .type = NLA_U16 }, | ||
295 | [NL80211_TXQ_ATTR_AIFS] = { .type = NLA_U8 }, | ||
296 | }; | ||
297 | |||
298 | static int parse_txq_params(struct nlattr *tb[], | ||
299 | struct ieee80211_txq_params *txq_params) | ||
300 | { | ||
301 | if (!tb[NL80211_TXQ_ATTR_QUEUE] || !tb[NL80211_TXQ_ATTR_TXOP] || | ||
302 | !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] || | ||
303 | !tb[NL80211_TXQ_ATTR_AIFS]) | ||
304 | return -EINVAL; | ||
305 | |||
306 | txq_params->queue = nla_get_u8(tb[NL80211_TXQ_ATTR_QUEUE]); | ||
307 | txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]); | ||
308 | txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]); | ||
309 | txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]); | ||
310 | txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]); | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | |||
287 | static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | 315 | static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) |
288 | { | 316 | { |
289 | struct cfg80211_registered_device *rdev; | 317 | struct cfg80211_registered_device *rdev; |
290 | int result; | 318 | int result = 0, rem_txq_params = 0; |
291 | 319 | struct nlattr *nl_txq_params; | |
292 | if (!info->attrs[NL80211_ATTR_WIPHY_NAME]) | ||
293 | return -EINVAL; | ||
294 | 320 | ||
295 | rdev = cfg80211_get_dev_from_info(info); | 321 | rdev = cfg80211_get_dev_from_info(info); |
296 | if (IS_ERR(rdev)) | 322 | if (IS_ERR(rdev)) |
297 | return PTR_ERR(rdev); | 323 | return PTR_ERR(rdev); |
298 | 324 | ||
299 | result = cfg80211_dev_rename(rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); | 325 | if (info->attrs[NL80211_ATTR_WIPHY_NAME]) { |
326 | result = cfg80211_dev_rename( | ||
327 | rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); | ||
328 | if (result) | ||
329 | goto bad_res; | ||
330 | } | ||
331 | |||
332 | if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) { | ||
333 | struct ieee80211_txq_params txq_params; | ||
334 | struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1]; | ||
335 | |||
336 | if (!rdev->ops->set_txq_params) { | ||
337 | result = -EOPNOTSUPP; | ||
338 | goto bad_res; | ||
339 | } | ||
300 | 340 | ||
341 | nla_for_each_nested(nl_txq_params, | ||
342 | info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], | ||
343 | rem_txq_params) { | ||
344 | nla_parse(tb, NL80211_TXQ_ATTR_MAX, | ||
345 | nla_data(nl_txq_params), | ||
346 | nla_len(nl_txq_params), | ||
347 | txq_params_policy); | ||
348 | result = parse_txq_params(tb, &txq_params); | ||
349 | if (result) | ||
350 | goto bad_res; | ||
351 | |||
352 | result = rdev->ops->set_txq_params(&rdev->wiphy, | ||
353 | &txq_params); | ||
354 | if (result) | ||
355 | goto bad_res; | ||
356 | } | ||
357 | } | ||
358 | |||
359 | bad_res: | ||
301 | cfg80211_put_dev(rdev); | 360 | cfg80211_put_dev(rdev); |
302 | return result; | 361 | return result; |
303 | } | 362 | } |
@@ -1613,6 +1672,12 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | |||
1613 | if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]) | 1672 | if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]) |
1614 | params.use_short_slot_time = | 1673 | params.use_short_slot_time = |
1615 | nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]); | 1674 | nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]); |
1675 | if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) { | ||
1676 | params.basic_rates = | ||
1677 | nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); | ||
1678 | params.basic_rates_len = | ||
1679 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); | ||
1680 | } | ||
1616 | 1681 | ||
1617 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1682 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1618 | if (err) | 1683 | if (err) |