diff options
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 66 |
1 files changed, 36 insertions, 30 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a3a152f55dd0..56d729c43b31 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -77,6 +77,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
77 | [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 }, | 77 | [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 }, |
78 | [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, | 78 | [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, |
79 | [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, | 79 | [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, |
80 | [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, | ||
80 | 81 | ||
81 | [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, | 82 | [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, |
82 | [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 }, | 83 | [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 }, |
@@ -492,7 +493,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
492 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | 493 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; |
493 | struct ieee80211_channel *chan; | 494 | struct ieee80211_channel *chan; |
494 | struct ieee80211_sta_ht_cap *ht_cap; | 495 | struct ieee80211_sta_ht_cap *ht_cap; |
495 | u32 freq, sec_freq; | 496 | u32 freq; |
496 | 497 | ||
497 | if (!rdev->ops->set_channel) { | 498 | if (!rdev->ops->set_channel) { |
498 | result = -EOPNOTSUPP; | 499 | result = -EOPNOTSUPP; |
@@ -518,33 +519,28 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
518 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) | 519 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) |
519 | goto bad_res; | 520 | goto bad_res; |
520 | 521 | ||
521 | if (channel_type == NL80211_CHAN_HT40MINUS) | 522 | if (channel_type == NL80211_CHAN_HT40MINUS && |
522 | sec_freq = freq - 20; | 523 | (chan->flags & IEEE80211_CHAN_NO_HT40MINUS)) |
523 | else if (channel_type == NL80211_CHAN_HT40PLUS) | 524 | goto bad_res; |
524 | sec_freq = freq + 20; | 525 | else if (channel_type == NL80211_CHAN_HT40PLUS && |
525 | else | 526 | (chan->flags & IEEE80211_CHAN_NO_HT40PLUS)) |
526 | sec_freq = 0; | ||
527 | |||
528 | ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; | ||
529 | |||
530 | /* no HT capabilities */ | ||
531 | if (channel_type != NL80211_CHAN_NO_HT && | ||
532 | !ht_cap->ht_supported) | ||
533 | goto bad_res; | 527 | goto bad_res; |
534 | 528 | ||
535 | if (sec_freq) { | 529 | /* |
536 | struct ieee80211_channel *schan; | 530 | * At this point we know if that if HT40 was requested |
531 | * we are allowed to use it and the extension channel | ||
532 | * exists. | ||
533 | */ | ||
534 | |||
535 | ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; | ||
537 | 536 | ||
538 | /* no 40 MHz capabilities */ | 537 | /* no HT capabilities or intolerant */ |
538 | if (channel_type != NL80211_CHAN_NO_HT) { | ||
539 | if (!ht_cap->ht_supported) | ||
540 | goto bad_res; | ||
539 | if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || | 541 | if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || |
540 | (ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)) | 542 | (ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)) |
541 | goto bad_res; | 543 | goto bad_res; |
542 | |||
543 | schan = ieee80211_get_channel(&rdev->wiphy, sec_freq); | ||
544 | |||
545 | /* Secondary channel not allowed */ | ||
546 | if (!schan || schan->flags & IEEE80211_CHAN_DISABLED) | ||
547 | goto bad_res; | ||
548 | } | 544 | } |
549 | 545 | ||
550 | result = rdev->ops->set_channel(&rdev->wiphy, chan, | 546 | result = rdev->ops->set_channel(&rdev->wiphy, chan, |
@@ -2571,18 +2567,24 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
2571 | rem_reg_rules) { | 2567 | rem_reg_rules) { |
2572 | num_rules++; | 2568 | num_rules++; |
2573 | if (num_rules > NL80211_MAX_SUPP_REG_RULES) | 2569 | if (num_rules > NL80211_MAX_SUPP_REG_RULES) |
2574 | goto bad_reg; | 2570 | return -EINVAL; |
2575 | } | 2571 | } |
2576 | 2572 | ||
2577 | if (!reg_is_valid_request(alpha2)) | 2573 | mutex_lock(&cfg80211_mutex); |
2578 | return -EINVAL; | 2574 | |
2575 | if (!reg_is_valid_request(alpha2)) { | ||
2576 | r = -EINVAL; | ||
2577 | goto bad_reg; | ||
2578 | } | ||
2579 | 2579 | ||
2580 | size_of_regd = sizeof(struct ieee80211_regdomain) + | 2580 | size_of_regd = sizeof(struct ieee80211_regdomain) + |
2581 | (num_rules * sizeof(struct ieee80211_reg_rule)); | 2581 | (num_rules * sizeof(struct ieee80211_reg_rule)); |
2582 | 2582 | ||
2583 | rd = kzalloc(size_of_regd, GFP_KERNEL); | 2583 | rd = kzalloc(size_of_regd, GFP_KERNEL); |
2584 | if (!rd) | 2584 | if (!rd) { |
2585 | return -ENOMEM; | 2585 | r = -ENOMEM; |
2586 | goto bad_reg; | ||
2587 | } | ||
2586 | 2588 | ||
2587 | rd->n_reg_rules = num_rules; | 2589 | rd->n_reg_rules = num_rules; |
2588 | rd->alpha2[0] = alpha2[0]; | 2590 | rd->alpha2[0] = alpha2[0]; |
@@ -2599,20 +2601,24 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
2599 | 2601 | ||
2600 | rule_idx++; | 2602 | rule_idx++; |
2601 | 2603 | ||
2602 | if (rule_idx > NL80211_MAX_SUPP_REG_RULES) | 2604 | if (rule_idx > NL80211_MAX_SUPP_REG_RULES) { |
2605 | r = -EINVAL; | ||
2603 | goto bad_reg; | 2606 | goto bad_reg; |
2607 | } | ||
2604 | } | 2608 | } |
2605 | 2609 | ||
2606 | BUG_ON(rule_idx != num_rules); | 2610 | BUG_ON(rule_idx != num_rules); |
2607 | 2611 | ||
2608 | mutex_lock(&cfg80211_mutex); | ||
2609 | r = set_regdom(rd); | 2612 | r = set_regdom(rd); |
2613 | |||
2610 | mutex_unlock(&cfg80211_mutex); | 2614 | mutex_unlock(&cfg80211_mutex); |
2615 | |||
2611 | return r; | 2616 | return r; |
2612 | 2617 | ||
2613 | bad_reg: | 2618 | bad_reg: |
2619 | mutex_unlock(&cfg80211_mutex); | ||
2614 | kfree(rd); | 2620 | kfree(rd); |
2615 | return -EINVAL; | 2621 | return r; |
2616 | } | 2622 | } |
2617 | 2623 | ||
2618 | static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | 2624 | static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) |