diff options
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/nl80211.c | 50 |
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 */ |
50 | static int get_rdev_dev_by_info_ifindex(struct genl_info *info, | 50 | static 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) | |||
4795 | static int nl80211_testmode_dump(struct sk_buff *skb, | 4794 | static 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(); |