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 /net/wireless/nl80211.c | |
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>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 28 |
1 files changed, 21 insertions, 7 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)); |