|
@@ -2731,6 +2731,69 @@ static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int nl80211_parse_mon_options(struct cfg80211_registered_device *rdev,
|
|
|
+ enum nl80211_iftype type,
|
|
|
+ struct genl_info *info,
|
|
|
+ struct vif_params *params)
|
|
|
+{
|
|
|
+ bool change = false;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
|
|
|
+ if (type != NL80211_IFTYPE_MONITOR)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
|
|
|
+ ¶ms->flags);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ change = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (params->flags & MONITOR_FLAG_ACTIVE &&
|
|
|
+ !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ if (info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]) {
|
|
|
+ const u8 *mumimo_groups;
|
|
|
+ u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
|
|
|
+
|
|
|
+ if (type != NL80211_IFTYPE_MONITOR)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ mumimo_groups =
|
|
|
+ nla_data(info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]);
|
|
|
+
|
|
|
+ /* bits 0 and 63 are reserved and must be zero */
|
|
|
+ if ((mumimo_groups[0] & BIT(7)) ||
|
|
|
+ (mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(0)))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ params->vht_mumimo_groups = mumimo_groups;
|
|
|
+ change = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]) {
|
|
|
+ u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
|
|
|
+
|
|
|
+ if (type != NL80211_IFTYPE_MONITOR)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ params->vht_mumimo_follow_addr =
|
|
|
+ nla_data(info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]);
|
|
|
+ change = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return change ? 1 : 0;
|
|
|
+}
|
|
|
+
|
|
|
static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
|
|
|
struct net_device *netdev, u8 use_4addr,
|
|
|
enum nl80211_iftype iftype)
|
|
@@ -2806,50 +2869,11 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
|
|
|
params.use_4addr = -1;
|
|
|
}
|
|
|
|
|
|
- if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
|
|
|
- if (ntype != NL80211_IFTYPE_MONITOR)
|
|
|
- return -EINVAL;
|
|
|
- err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
|
|
|
- ¶ms.flags);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- change = true;
|
|
|
- }
|
|
|
-
|
|
|
- if (params.flags & MONITOR_FLAG_ACTIVE &&
|
|
|
- !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
|
|
|
- return -EOPNOTSUPP;
|
|
|
-
|
|
|
- if (info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]) {
|
|
|
- const u8 *mumimo_groups;
|
|
|
- u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
|
|
|
-
|
|
|
- if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
|
|
|
- return -EOPNOTSUPP;
|
|
|
-
|
|
|
- mumimo_groups =
|
|
|
- nla_data(info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]);
|
|
|
-
|
|
|
- /* bits 0 and 63 are reserved and must be zero */
|
|
|
- if ((mumimo_groups[0] & BIT(7)) ||
|
|
|
- (mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(0)))
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- params.vht_mumimo_groups = mumimo_groups;
|
|
|
- change = true;
|
|
|
- }
|
|
|
-
|
|
|
- if (info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]) {
|
|
|
- u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
|
|
|
-
|
|
|
- if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
|
|
|
- return -EOPNOTSUPP;
|
|
|
-
|
|
|
- params.vht_mumimo_follow_addr =
|
|
|
- nla_data(info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]);
|
|
|
+ err = nl80211_parse_mon_options(rdev, ntype, info, ¶ms);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+ if (err > 0)
|
|
|
change = true;
|
|
|
- }
|
|
|
|
|
|
if (change)
|
|
|
err = cfg80211_change_iface(rdev, dev, ntype, ¶ms);
|
|
@@ -2905,19 +2929,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
- if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
|
|
|
- if (type != NL80211_IFTYPE_MONITOR)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
|
|
|
- ¶ms.flags);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
- }
|
|
|
-
|
|
|
- if (params.flags & MONITOR_FLAG_ACTIVE &&
|
|
|
- !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
|
|
|
- return -EOPNOTSUPP;
|
|
|
+ err = nl80211_parse_mon_options(rdev, type, info, ¶ms);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
|
|
|
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
|
|
if (!msg)
|