Commit ac7f9cfa authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

cfg80211: accept no-op interface mode changes

When somebody tries to set the interface mode to the existing
mode, don't ask the driver but silently accept the setting.
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 86f04680
...@@ -607,6 +607,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) ...@@ -607,6 +607,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
enum nl80211_iftype type; enum nl80211_iftype type;
struct net_device *dev; struct net_device *dev;
u32 _flags, *flags = NULL; u32 _flags, *flags = NULL;
bool change = false;
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
...@@ -620,12 +621,18 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) ...@@ -620,12 +621,18 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
type = dev->ieee80211_ptr->iftype; type = dev->ieee80211_ptr->iftype;
dev_put(dev); dev_put(dev);
err = -EINVAL;
if (info->attrs[NL80211_ATTR_IFTYPE]) { if (info->attrs[NL80211_ATTR_IFTYPE]) {
type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); enum nl80211_iftype ntype;
if (type > NL80211_IFTYPE_MAX)
ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
if (type != ntype)
change = true;
type = ntype;
if (type > NL80211_IFTYPE_MAX) {
err = -EINVAL;
goto unlock; goto unlock;
} }
}
if (!drv->ops->change_virtual_intf || if (!drv->ops->change_virtual_intf ||
!(drv->wiphy.interface_modes & (1 << type))) { !(drv->wiphy.interface_modes & (1 << type))) {
...@@ -640,6 +647,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) ...@@ -640,6 +647,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
} }
params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
change = true;
} }
if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
...@@ -649,12 +657,18 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) ...@@ -649,12 +657,18 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
} }
err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS], err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
&_flags); &_flags);
if (!err) if (err)
goto unlock;
flags = &_flags; flags = &_flags;
change = true;
} }
if (change)
err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
type, flags, &params); type, flags, &params);
else
err = 0;
dev = __dev_get_by_index(&init_net, ifindex); dev = __dev_get_by_index(&init_net, ifindex);
WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type));
......
...@@ -66,6 +66,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, ...@@ -66,6 +66,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
struct cfg80211_registered_device *rdev; struct cfg80211_registered_device *rdev;
struct vif_params vifparams; struct vif_params vifparams;
enum nl80211_iftype type; enum nl80211_iftype type;
int ret;
if (!wdev) if (!wdev)
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -96,10 +97,16 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, ...@@ -96,10 +97,16 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
return -EINVAL; return -EINVAL;
} }
if (type == wdev->iftype)
return 0;
memset(&vifparams, 0, sizeof(vifparams)); memset(&vifparams, 0, sizeof(vifparams));
return rdev->ops->change_virtual_intf(wdev->wiphy, dev->ifindex, type, ret = rdev->ops->change_virtual_intf(wdev->wiphy, dev->ifindex, type,
NULL, &vifparams); NULL, &vifparams);
WARN_ON(!ret && wdev->iftype != type);
return ret;
} }
EXPORT_SYMBOL(cfg80211_wext_siwmode); EXPORT_SYMBOL(cfg80211_wext_siwmode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment