diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-03-21 12:07:59 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-27 20:13:08 -0400 |
commit | ac7f9cfa2c3b810e0adfb889ad407a8c79a84dbe (patch) | |
tree | 599a601a2adc5e3806a4bb665491dd08fe2eb3ff | |
parent | 86f04680df4a136a4a90501572dc2f31f8426581 (diff) |
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: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | net/wireless/nl80211.c | 28 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 11 |
2 files changed, 30 insertions, 9 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a7d0b94f6b5e..8808431bd581 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -607,6 +607,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
607 | enum nl80211_iftype type; | 607 | enum nl80211_iftype type; |
608 | struct net_device *dev; | 608 | struct net_device *dev; |
609 | u32 _flags, *flags = NULL; | 609 | u32 _flags, *flags = NULL; |
610 | bool change = false; | ||
610 | 611 | ||
611 | memset(¶ms, 0, sizeof(params)); | 612 | memset(¶ms, 0, sizeof(params)); |
612 | 613 | ||
@@ -620,11 +621,17 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
620 | type = dev->ieee80211_ptr->iftype; | 621 | type = dev->ieee80211_ptr->iftype; |
621 | dev_put(dev); | 622 | dev_put(dev); |
622 | 623 | ||
623 | err = -EINVAL; | ||
624 | if (info->attrs[NL80211_ATTR_IFTYPE]) { | 624 | if (info->attrs[NL80211_ATTR_IFTYPE]) { |
625 | type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); | 625 | enum nl80211_iftype ntype; |
626 | if (type > NL80211_IFTYPE_MAX) | 626 | |
627 | ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); | ||
628 | if (type != ntype) | ||
629 | change = true; | ||
630 | type = ntype; | ||
631 | if (type > NL80211_IFTYPE_MAX) { | ||
632 | err = -EINVAL; | ||
627 | goto unlock; | 633 | goto unlock; |
634 | } | ||
628 | } | 635 | } |
629 | 636 | ||
630 | if (!drv->ops->change_virtual_intf || | 637 | if (!drv->ops->change_virtual_intf || |
@@ -640,6 +647,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
640 | } | 647 | } |
641 | params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); | 648 | params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); |
642 | params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); | 649 | params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); |
650 | change = true; | ||
643 | } | 651 | } |
644 | 652 | ||
645 | if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { | 653 | 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 | } | 657 | } |
650 | err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS], | 658 | err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS], |
651 | &_flags); | 659 | &_flags); |
652 | if (!err) | 660 | if (err) |
653 | flags = &_flags; | 661 | goto unlock; |
662 | |||
663 | flags = &_flags; | ||
664 | change = true; | ||
654 | } | 665 | } |
655 | 666 | ||
656 | err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, | 667 | if (change) |
657 | type, flags, ¶ms); | 668 | err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, |
669 | type, flags, ¶ms); | ||
670 | else | ||
671 | err = 0; | ||
658 | 672 | ||
659 | dev = __dev_get_by_index(&init_net, ifindex); | 673 | dev = __dev_get_by_index(&init_net, ifindex); |
660 | WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); | 674 | WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index b84a9b4fe96a..0fd1db6e95bb 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -66,6 +66,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, | |||
66 | struct cfg80211_registered_device *rdev; | 66 | struct cfg80211_registered_device *rdev; |
67 | struct vif_params vifparams; | 67 | struct vif_params vifparams; |
68 | enum nl80211_iftype type; | 68 | enum nl80211_iftype type; |
69 | int ret; | ||
69 | 70 | ||
70 | if (!wdev) | 71 | if (!wdev) |
71 | return -EOPNOTSUPP; | 72 | return -EOPNOTSUPP; |
@@ -96,10 +97,16 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, | |||
96 | return -EINVAL; | 97 | return -EINVAL; |
97 | } | 98 | } |
98 | 99 | ||
100 | if (type == wdev->iftype) | ||
101 | return 0; | ||
102 | |||
99 | memset(&vifparams, 0, sizeof(vifparams)); | 103 | memset(&vifparams, 0, sizeof(vifparams)); |
100 | 104 | ||
101 | return rdev->ops->change_virtual_intf(wdev->wiphy, dev->ifindex, type, | 105 | ret = rdev->ops->change_virtual_intf(wdev->wiphy, dev->ifindex, type, |
102 | NULL, &vifparams); | 106 | NULL, &vifparams); |
107 | WARN_ON(!ret && wdev->iftype != type); | ||
108 | |||
109 | return ret; | ||
103 | } | 110 | } |
104 | EXPORT_SYMBOL(cfg80211_wext_siwmode); | 111 | EXPORT_SYMBOL(cfg80211_wext_siwmode); |
105 | 112 | ||