mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-10 07:00:48 +00:00
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>
This commit is contained in:
parent
5d22df200b
commit
00918d33c0
@ -47,22 +47,21 @@ static struct genl_family nl80211_fam = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* internal helper: get rdev and dev */
|
/* internal helper: get rdev and dev */
|
||||||
static int get_rdev_dev_by_info_ifindex(struct genl_info *info,
|
static int get_rdev_dev_by_ifindex(struct net *netns, struct nlattr **attrs,
|
||||||
struct cfg80211_registered_device **rdev,
|
struct cfg80211_registered_device **rdev,
|
||||||
struct net_device **dev)
|
struct net_device **dev)
|
||||||
{
|
{
|
||||||
struct nlattr **attrs = info->attrs;
|
|
||||||
int ifindex;
|
int ifindex;
|
||||||
|
|
||||||
if (!attrs[NL80211_ATTR_IFINDEX])
|
if (!attrs[NL80211_ATTR_IFINDEX])
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
|
ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
|
||||||
*dev = dev_get_by_index(genl_info_net(info), ifindex);
|
*dev = dev_get_by_index(netns, ifindex);
|
||||||
if (!*dev)
|
if (!*dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
*rdev = cfg80211_get_dev_from_ifindex(genl_info_net(info), ifindex);
|
*rdev = cfg80211_get_dev_from_ifindex(netns, ifindex);
|
||||||
if (IS_ERR(*rdev)) {
|
if (IS_ERR(*rdev)) {
|
||||||
dev_put(*dev);
|
dev_put(*dev);
|
||||||
return PTR_ERR(*rdev);
|
return PTR_ERR(*rdev);
|
||||||
@ -4795,7 +4794,7 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
|
|||||||
static int nl80211_testmode_dump(struct sk_buff *skb,
|
static int nl80211_testmode_dump(struct sk_buff *skb,
|
||||||
struct netlink_callback *cb)
|
struct netlink_callback *cb)
|
||||||
{
|
{
|
||||||
struct cfg80211_registered_device *dev;
|
struct cfg80211_registered_device *rdev;
|
||||||
int err;
|
int err;
|
||||||
long phy_idx;
|
long phy_idx;
|
||||||
void *data = NULL;
|
void *data = NULL;
|
||||||
@ -4813,9 +4812,21 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
|
|||||||
nl80211_policy);
|
nl80211_policy);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
if (!nl80211_fam.attrbuf[NL80211_ATTR_WIPHY])
|
if (nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]) {
|
||||||
return -EINVAL;
|
phy_idx = nla_get_u32(
|
||||||
phy_idx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]);
|
nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]);
|
||||||
|
} else {
|
||||||
|
struct net_device *netdev;
|
||||||
|
|
||||||
|
err = get_rdev_dev_by_ifindex(sock_net(skb->sk),
|
||||||
|
nl80211_fam.attrbuf,
|
||||||
|
&rdev, &netdev);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
dev_put(netdev);
|
||||||
|
phy_idx = rdev->wiphy_idx;
|
||||||
|
cfg80211_unlock_rdev(rdev);
|
||||||
|
}
|
||||||
if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
|
if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
|
||||||
cb->args[1] =
|
cb->args[1] =
|
||||||
(long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA];
|
(long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA];
|
||||||
@ -4827,15 +4838,15 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&cfg80211_mutex);
|
mutex_lock(&cfg80211_mutex);
|
||||||
dev = cfg80211_rdev_by_wiphy_idx(phy_idx);
|
rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
|
||||||
if (!dev) {
|
if (!rdev) {
|
||||||
mutex_unlock(&cfg80211_mutex);
|
mutex_unlock(&cfg80211_mutex);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
cfg80211_lock_rdev(dev);
|
cfg80211_lock_rdev(rdev);
|
||||||
mutex_unlock(&cfg80211_mutex);
|
mutex_unlock(&cfg80211_mutex);
|
||||||
|
|
||||||
if (!dev->ops->testmode_dump) {
|
if (!rdev->ops->testmode_dump) {
|
||||||
err = -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
@ -4846,7 +4857,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
|
|||||||
NL80211_CMD_TESTMODE);
|
NL80211_CMD_TESTMODE);
|
||||||
struct nlattr *tmdata;
|
struct nlattr *tmdata;
|
||||||
|
|
||||||
if (nla_put_u32(skb, NL80211_ATTR_WIPHY, dev->wiphy_idx) < 0) {
|
if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx) < 0) {
|
||||||
genlmsg_cancel(skb, hdr);
|
genlmsg_cancel(skb, hdr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -4856,8 +4867,8 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
|
|||||||
genlmsg_cancel(skb, hdr);
|
genlmsg_cancel(skb, hdr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
err = dev->ops->testmode_dump(&dev->wiphy, skb, cb,
|
err = rdev->ops->testmode_dump(&rdev->wiphy, skb, cb,
|
||||||
data, data_len);
|
data, data_len);
|
||||||
nla_nest_end(skb, tmdata);
|
nla_nest_end(skb, tmdata);
|
||||||
|
|
||||||
if (err == -ENOBUFS || err == -ENOENT) {
|
if (err == -ENOBUFS || err == -ENOENT) {
|
||||||
@ -4875,7 +4886,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
|
|||||||
/* see above */
|
/* see above */
|
||||||
cb->args[0] = phy_idx + 1;
|
cb->args[0] = phy_idx + 1;
|
||||||
out_err:
|
out_err:
|
||||||
cfg80211_unlock_rdev(dev);
|
cfg80211_unlock_rdev(rdev);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6110,7 +6121,8 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
|
|||||||
}
|
}
|
||||||
info->user_ptr[0] = rdev;
|
info->user_ptr[0] = rdev;
|
||||||
} else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
|
} else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
|
||||||
err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
|
err = get_rdev_dev_by_ifindex(genl_info_net(info), info->attrs,
|
||||||
|
&rdev, &dev);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (rtnl)
|
if (rtnl)
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user