aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-03-21 12:07:59 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-03-27 20:13:08 -0400
commitac7f9cfa2c3b810e0adfb889ad407a8c79a84dbe (patch)
tree599a601a2adc5e3806a4bb665491dd08fe2eb3ff
parent86f04680df4a136a4a90501572dc2f31f8426581 (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.c28
-rw-r--r--net/wireless/wext-compat.c11
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(&params, 0, sizeof(params)); 612 memset(&params, 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, &params); 668 err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
669 type, flags, &params);
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}
104EXPORT_SYMBOL(cfg80211_wext_siwmode); 111EXPORT_SYMBOL(cfg80211_wext_siwmode);
105 112