aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c93
1 files changed, 90 insertions, 3 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index db71150b8040..37902a54e9c1 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -153,6 +153,9 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
153 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, }, 153 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
154 [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG }, 154 [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
155 [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 }, 155 [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 },
156
157 [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
158 [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 },
156}; 159};
157 160
158/* policy for the attributes */ 161/* policy for the attributes */
@@ -869,6 +872,34 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
869 goto bad_res; 872 goto bad_res;
870 } 873 }
871 874
875 if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) {
876 enum nl80211_tx_power_setting type;
877 int idx, mbm = 0;
878
879 if (!rdev->ops->set_tx_power) {
880 result = -EOPNOTSUPP;
881 goto bad_res;
882 }
883
884 idx = NL80211_ATTR_WIPHY_TX_POWER_SETTING;
885 type = nla_get_u32(info->attrs[idx]);
886
887 if (!info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] &&
888 (type != NL80211_TX_POWER_AUTOMATIC)) {
889 result = -EINVAL;
890 goto bad_res;
891 }
892
893 if (type != NL80211_TX_POWER_AUTOMATIC) {
894 idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL;
895 mbm = nla_get_u32(info->attrs[idx]);
896 }
897
898 result = rdev->ops->set_tx_power(&rdev->wiphy, type, mbm);
899 if (result)
900 goto bad_res;
901 }
902
872 changed = 0; 903 changed = 0;
873 904
874 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) { 905 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
@@ -1107,7 +1138,7 @@ static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
1107 enum nl80211_iftype iftype) 1138 enum nl80211_iftype iftype)
1108{ 1139{
1109 if (!use_4addr) { 1140 if (!use_4addr) {
1110 if (netdev && netdev->br_port) 1141 if (netdev && (netdev->priv_flags & IFF_BRIDGE_PORT))
1111 return -EBUSY; 1142 return -EBUSY;
1112 return 0; 1143 return 0;
1113 } 1144 }
@@ -2738,6 +2769,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
2738 2769
2739 nla_put_failure: 2770 nla_put_failure:
2740 genlmsg_cancel(msg, hdr); 2771 genlmsg_cancel(msg, hdr);
2772 nlmsg_free(msg);
2741 err = -EMSGSIZE; 2773 err = -EMSGSIZE;
2742 out: 2774 out:
2743 /* Cleanup */ 2775 /* Cleanup */
@@ -2929,6 +2961,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
2929 2961
2930nla_put_failure: 2962nla_put_failure:
2931 genlmsg_cancel(msg, hdr); 2963 genlmsg_cancel(msg, hdr);
2964 nlmsg_free(msg);
2932 err = -EMSGSIZE; 2965 err = -EMSGSIZE;
2933out: 2966out:
2934 mutex_unlock(&cfg80211_mutex); 2967 mutex_unlock(&cfg80211_mutex);
@@ -3955,6 +3988,55 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
3955 } 3988 }
3956 } 3989 }
3957 3990
3991 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
3992 u8 *rates =
3993 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
3994 int n_rates =
3995 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
3996 struct ieee80211_supported_band *sband =
3997 wiphy->bands[ibss.channel->band];
3998 int i, j;
3999
4000 if (n_rates == 0) {
4001 err = -EINVAL;
4002 goto out;
4003 }
4004
4005 for (i = 0; i < n_rates; i++) {
4006 int rate = (rates[i] & 0x7f) * 5;
4007 bool found = false;
4008
4009 for (j = 0; j < sband->n_bitrates; j++) {
4010 if (sband->bitrates[j].bitrate == rate) {
4011 found = true;
4012 ibss.basic_rates |= BIT(j);
4013 break;
4014 }
4015 }
4016 if (!found) {
4017 err = -EINVAL;
4018 goto out;
4019 }
4020 }
4021 } else {
4022 /*
4023 * If no rates were explicitly configured,
4024 * use the mandatory rate set for 11b or
4025 * 11a for maximum compatibility.
4026 */
4027 struct ieee80211_supported_band *sband =
4028 wiphy->bands[ibss.channel->band];
4029 int j;
4030 u32 flag = ibss.channel->band == IEEE80211_BAND_5GHZ ?
4031 IEEE80211_RATE_MANDATORY_A :
4032 IEEE80211_RATE_MANDATORY_B;
4033
4034 for (j = 0; j < sband->n_bitrates; j++) {
4035 if (sband->bitrates[j].flags & flag)
4036 ibss.basic_rates |= BIT(j);
4037 }
4038 }
4039
3958 err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); 4040 err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
3959 4041
3960out: 4042out:
@@ -4653,7 +4735,8 @@ static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info)
4653 if (err) 4735 if (err)
4654 goto unlock_rtnl; 4736 goto unlock_rtnl;
4655 4737
4656 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { 4738 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4739 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) {
4657 err = -EOPNOTSUPP; 4740 err = -EOPNOTSUPP;
4658 goto out; 4741 goto out;
4659 } 4742 }
@@ -4681,6 +4764,7 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info)
4681 struct net_device *dev; 4764 struct net_device *dev;
4682 struct ieee80211_channel *chan; 4765 struct ieee80211_channel *chan;
4683 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; 4766 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
4767 bool channel_type_valid = false;
4684 u32 freq; 4768 u32 freq;
4685 int err; 4769 int err;
4686 void *hdr; 4770 void *hdr;
@@ -4702,7 +4786,8 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info)
4702 goto out; 4786 goto out;
4703 } 4787 }
4704 4788
4705 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { 4789 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4790 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) {
4706 err = -EOPNOTSUPP; 4791 err = -EOPNOTSUPP;
4707 goto out; 4792 goto out;
4708 } 4793 }
@@ -4722,6 +4807,7 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info)
4722 err = -EINVAL; 4807 err = -EINVAL;
4723 goto out; 4808 goto out;
4724 } 4809 }
4810 channel_type_valid = true;
4725 } 4811 }
4726 4812
4727 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); 4813 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
@@ -4745,6 +4831,7 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info)
4745 goto free_msg; 4831 goto free_msg;
4746 } 4832 }
4747 err = cfg80211_mlme_action(rdev, dev, chan, channel_type, 4833 err = cfg80211_mlme_action(rdev, dev, chan, channel_type,
4834 channel_type_valid,
4748 nla_data(info->attrs[NL80211_ATTR_FRAME]), 4835 nla_data(info->attrs[NL80211_ATTR_FRAME]),
4749 nla_len(info->attrs[NL80211_ATTR_FRAME]), 4836 nla_len(info->attrs[NL80211_ATTR_FRAME]),
4750 &cookie); 4837 &cookie);