diff options
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/nl80211.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c9141e3df9ba..9caee6022e3f 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -59,6 +59,8 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
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 | [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, |
62 | [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, | ||
63 | [NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET] = { .type = NLA_U32 }, | ||
62 | 64 | ||
63 | [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, | 65 | [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, |
64 | [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, | 66 | [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, |
@@ -359,6 +361,61 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
359 | } | 361 | } |
360 | } | 362 | } |
361 | 363 | ||
364 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | ||
365 | enum nl80211_sec_chan_offset sec_chan_offset = | ||
366 | NL80211_SEC_CHAN_NO_HT; | ||
367 | struct ieee80211_channel *chan; | ||
368 | u32 freq, sec_freq; | ||
369 | |||
370 | if (!rdev->ops->set_channel) { | ||
371 | result = -EOPNOTSUPP; | ||
372 | goto bad_res; | ||
373 | } | ||
374 | |||
375 | if (info->attrs[NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]) { | ||
376 | sec_chan_offset = nla_get_u32( | ||
377 | info->attrs[ | ||
378 | NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]); | ||
379 | if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT && | ||
380 | sec_chan_offset != NL80211_SEC_CHAN_DISABLED && | ||
381 | sec_chan_offset != NL80211_SEC_CHAN_BELOW && | ||
382 | sec_chan_offset != NL80211_SEC_CHAN_ABOVE) { | ||
383 | result = -EINVAL; | ||
384 | goto bad_res; | ||
385 | } | ||
386 | } | ||
387 | |||
388 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | ||
389 | chan = ieee80211_get_channel(&rdev->wiphy, freq); | ||
390 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) { | ||
391 | /* Primary channel not allowed */ | ||
392 | result = -EINVAL; | ||
393 | goto bad_res; | ||
394 | } | ||
395 | if (sec_chan_offset == NL80211_SEC_CHAN_BELOW) | ||
396 | sec_freq = freq - 20; | ||
397 | else if (sec_chan_offset == NL80211_SEC_CHAN_ABOVE) | ||
398 | sec_freq = freq + 20; | ||
399 | else | ||
400 | sec_freq = 0; | ||
401 | |||
402 | if (sec_freq) { | ||
403 | struct ieee80211_channel *schan; | ||
404 | schan = ieee80211_get_channel(&rdev->wiphy, sec_freq); | ||
405 | if (!schan || schan->flags & IEEE80211_CHAN_DISABLED) { | ||
406 | /* Secondary channel not allowed */ | ||
407 | result = -EINVAL; | ||
408 | goto bad_res; | ||
409 | } | ||
410 | } | ||
411 | |||
412 | result = rdev->ops->set_channel(&rdev->wiphy, chan, | ||
413 | sec_chan_offset); | ||
414 | if (result) | ||
415 | goto bad_res; | ||
416 | } | ||
417 | |||
418 | |||
362 | bad_res: | 419 | bad_res: |
363 | cfg80211_put_dev(rdev); | 420 | cfg80211_put_dev(rdev); |
364 | return result; | 421 | return result; |