diff options
Diffstat (limited to 'net/wireless/nl80211.c')
| -rw-r--r-- | net/wireless/nl80211.c | 93 |
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 | ||
| 2930 | nla_put_failure: | 2962 | nla_put_failure: |
| 2931 | genlmsg_cancel(msg, hdr); | 2963 | genlmsg_cancel(msg, hdr); |
| 2964 | nlmsg_free(msg); | ||
| 2932 | err = -EMSGSIZE; | 2965 | err = -EMSGSIZE; |
| 2933 | out: | 2966 | out: |
| 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 | ||
| 3960 | out: | 4042 | out: |
| @@ -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); |
