aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-12-13 11:22:05 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-12-14 14:50:11 -0500
commit00918d33c0e9966392e5a13aeacd712b9da473c9 (patch)
treea0fd2e1efffc820244f371cb15652a88ecf38715 /net/wireless
parent5d22df200beccb1dea26fe4d8684ed93ae2f0aeb (diff)
nl80211: accept testmode dump with netdev
All nl80211 commands that need only the wiphy still allow identifying it by giving an interface index, except, as Kenny pointed out, the testmode dump support. Fix this by looking up the wiphy via the ifidx in this case as well. Tested-by: Kenny Hsu <kenny.hsu@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c50
1 files changed, 31 insertions, 19 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index ba439664c2e0..4d708cea390f 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -47,22 +47,21 @@ static struct genl_family nl80211_fam = {
47}; 47};
48 48
49/* internal helper: get rdev and dev */ 49/* internal helper: get rdev and dev */
50static int get_rdev_dev_by_info_ifindex(struct genl_info *info, 50static int get_rdev_dev_by_ifindex(struct net *netns, struct nlattr **attrs,
51 struct cfg80211_registered_device **rdev, 51 struct cfg80211_registered_device **rdev,
52 struct net_device **dev) 52 struct net_device **dev)
53{ 53{
54 struct nlattr **attrs = info->attrs;
55 int ifindex; 54 int ifindex;
56 55
57 if (!attrs[NL80211_ATTR_IFINDEX]) 56 if (!attrs[NL80211_ATTR_IFINDEX])
58 return -EINVAL; 57 return -EINVAL;
59 58
60 ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]); 59 ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
61 *dev = dev_get_by_index(genl_info_net(info), ifindex); 60 *dev = dev_get_by_index(netns, ifindex);
62 if (!*dev) 61 if (!*dev)
63 return -ENODEV; 62 return -ENODEV;
64 63
65 *rdev = cfg80211_get_dev_from_ifindex(genl_info_net(info), ifindex); 64 *rdev = cfg80211_get_dev_from_ifindex(netns, ifindex);
66 if (IS_ERR(*rdev)) { 65 if (IS_ERR(*rdev)) {
67 dev_put(*dev); 66 dev_put(*dev);
68 return PTR_ERR(*rdev); 67 return PTR_ERR(*rdev);
@@ -4795,7 +4794,7 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
4795static int nl80211_testmode_dump(struct sk_buff *skb, 4794static int nl80211_testmode_dump(struct sk_buff *skb,
4796 struct netlink_callback *cb) 4795 struct netlink_callback *cb)
4797{ 4796{
4798 struct cfg80211_registered_device *dev; 4797 struct cfg80211_registered_device *rdev;
4799 int err; 4798 int err;
4800 long phy_idx; 4799 long phy_idx;
4801 void *data = NULL; 4800 void *data = NULL;
@@ -4813,9 +4812,21 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
4813 nl80211_policy); 4812 nl80211_policy);
4814 if (err) 4813 if (err)
4815 return err; 4814 return err;
4816 if (!nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]) 4815 if (nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]) {
4817 return -EINVAL; 4816 phy_idx = nla_get_u32(
4818 phy_idx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]); 4817 nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]);
4818 } else {
4819 struct net_device *netdev;
4820
4821 err = get_rdev_dev_by_ifindex(sock_net(skb->sk),
4822 nl80211_fam.attrbuf,
4823 &rdev, &netdev);
4824 if (err)
4825 return err;
4826 dev_put(netdev);
4827 phy_idx = rdev->wiphy_idx;
4828 cfg80211_unlock_rdev(rdev);
4829 }
4819 if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]) 4830 if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
4820 cb->args[1] = 4831 cb->args[1] =
4821 (long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]; 4832 (long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA];
@@ -4827,15 +4838,15 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
4827 } 4838 }
4828 4839
4829 mutex_lock(&cfg80211_mutex); 4840 mutex_lock(&cfg80211_mutex);
4830 dev = cfg80211_rdev_by_wiphy_idx(phy_idx); 4841 rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
4831 if (!dev) { 4842 if (!rdev) {
4832 mutex_unlock(&cfg80211_mutex); 4843 mutex_unlock(&cfg80211_mutex);
4833 return -ENOENT; 4844 return -ENOENT;
4834 } 4845 }
4835 cfg80211_lock_rdev(dev); 4846 cfg80211_lock_rdev(rdev);
4836 mutex_unlock(&cfg80211_mutex); 4847 mutex_unlock(&cfg80211_mutex);
4837 4848
4838 if (!dev->ops->testmode_dump) { 4849 if (!rdev->ops->testmode_dump) {
4839 err = -EOPNOTSUPP; 4850 err = -EOPNOTSUPP;
4840 goto out_err; 4851 goto out_err;
4841 } 4852 }
@@ -4846,7 +4857,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
4846 NL80211_CMD_TESTMODE); 4857 NL80211_CMD_TESTMODE);
4847 struct nlattr *tmdata; 4858 struct nlattr *tmdata;
4848 4859
4849 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, dev->wiphy_idx) < 0) { 4860 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx) < 0) {
4850 genlmsg_cancel(skb, hdr); 4861 genlmsg_cancel(skb, hdr);
4851 break; 4862 break;
4852 } 4863 }
@@ -4856,8 +4867,8 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
4856 genlmsg_cancel(skb, hdr); 4867 genlmsg_cancel(skb, hdr);
4857 break; 4868 break;
4858 } 4869 }
4859 err = dev->ops->testmode_dump(&dev->wiphy, skb, cb, 4870 err = rdev->ops->testmode_dump(&rdev->wiphy, skb, cb,
4860 data, data_len); 4871 data, data_len);
4861 nla_nest_end(skb, tmdata); 4872 nla_nest_end(skb, tmdata);
4862 4873
4863 if (err == -ENOBUFS || err == -ENOENT) { 4874 if (err == -ENOBUFS || err == -ENOENT) {
@@ -4875,7 +4886,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
4875 /* see above */ 4886 /* see above */
4876 cb->args[0] = phy_idx + 1; 4887 cb->args[0] = phy_idx + 1;
4877 out_err: 4888 out_err:
4878 cfg80211_unlock_rdev(dev); 4889 cfg80211_unlock_rdev(rdev);
4879 return err; 4890 return err;
4880} 4891}
4881 4892
@@ -6110,7 +6121,8 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
6110 } 6121 }
6111 info->user_ptr[0] = rdev; 6122 info->user_ptr[0] = rdev;
6112 } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) { 6123 } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
6113 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); 6124 err = get_rdev_dev_by_ifindex(genl_info_net(info), info->attrs,
6125 &rdev, &dev);
6114 if (err) { 6126 if (err) {
6115 if (rtnl) 6127 if (rtnl)
6116 rtnl_unlock(); 6128 rtnl_unlock();