|
@@ -968,6 +968,28 @@ static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
|
|
|
+ u8 use_4addr, enum nl80211_iftype iftype)
|
|
|
+{
|
|
|
+ if (!use_4addr)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ switch (iftype) {
|
|
|
+ case NL80211_IFTYPE_AP_VLAN:
|
|
|
+ if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP)
|
|
|
+ return 0;
|
|
|
+ break;
|
|
|
+ case NL80211_IFTYPE_STATION:
|
|
|
+ if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_STATION)
|
|
|
+ return 0;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+}
|
|
|
+
|
|
|
static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
|
|
|
{
|
|
|
struct cfg80211_registered_device *rdev;
|
|
@@ -1011,6 +1033,9 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
|
|
|
if (info->attrs[NL80211_ATTR_4ADDR]) {
|
|
|
params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
|
|
|
change = true;
|
|
|
+ err = nl80211_valid_4addr(rdev, params.use_4addr, ntype);
|
|
|
+ if (err)
|
|
|
+ goto unlock;
|
|
|
} else {
|
|
|
params.use_4addr = -1;
|
|
|
}
|
|
@@ -1034,6 +1059,9 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
|
|
|
else
|
|
|
err = 0;
|
|
|
|
|
|
+ if (!err && params.use_4addr != -1)
|
|
|
+ dev->ieee80211_ptr->use_4addr = params.use_4addr;
|
|
|
+
|
|
|
unlock:
|
|
|
dev_put(dev);
|
|
|
cfg80211_unlock_rdev(rdev);
|
|
@@ -1081,8 +1109,12 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
|
|
|
params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
|
|
|
}
|
|
|
|
|
|
- if (info->attrs[NL80211_ATTR_4ADDR])
|
|
|
+ if (info->attrs[NL80211_ATTR_4ADDR]) {
|
|
|
params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
|
|
|
+ err = nl80211_valid_4addr(rdev, params.use_4addr, type);
|
|
|
+ if (err)
|
|
|
+ goto unlock;
|
|
|
+ }
|
|
|
|
|
|
err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
|
|
|
info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
|