};
/* internal helper: get rdev and dev */
-static int get_rdev_dev_by_info_ifindex(struct genl_info *info,
- struct cfg80211_registered_device **rdev,
- struct net_device **dev)
+static int get_rdev_dev_by_ifindex(struct net *netns, struct nlattr **attrs,
+ struct cfg80211_registered_device **rdev,
+ struct net_device **dev)
{
- struct nlattr **attrs = info->attrs;
int ifindex;
if (!attrs[NL80211_ATTR_IFINDEX])
return -EINVAL;
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)
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)) {
dev_put(*dev);
return PTR_ERR(*rdev);
static int nl80211_testmode_dump(struct sk_buff *skb,
struct netlink_callback *cb)
{
- struct cfg80211_registered_device *dev;
+ struct cfg80211_registered_device *rdev;
int err;
long phy_idx;
void *data = NULL;
nl80211_policy);
if (err)
return err;
- if (!nl80211_fam.attrbuf[NL80211_ATTR_WIPHY])
- return -EINVAL;
- phy_idx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]);
+ if (nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]) {
+ phy_idx = nla_get_u32(
+ 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])
cb->args[1] =
(long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA];
}
mutex_lock(&cfg80211_mutex);
- dev = cfg80211_rdev_by_wiphy_idx(phy_idx);
- if (!dev) {
+ rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
+ if (!rdev) {
mutex_unlock(&cfg80211_mutex);
return -ENOENT;
}
- cfg80211_lock_rdev(dev);
+ cfg80211_lock_rdev(rdev);
mutex_unlock(&cfg80211_mutex);
- if (!dev->ops->testmode_dump) {
+ if (!rdev->ops->testmode_dump) {
err = -EOPNOTSUPP;
goto out_err;
}
NL80211_CMD_TESTMODE);
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);
break;
}
genlmsg_cancel(skb, hdr);
break;
}
- err = dev->ops->testmode_dump(&dev->wiphy, skb, cb,
- data, data_len);
+ err = rdev->ops->testmode_dump(&rdev->wiphy, skb, cb,
+ data, data_len);
nla_nest_end(skb, tmdata);
if (err == -ENOBUFS || err == -ENOENT) {
/* see above */
cb->args[0] = phy_idx + 1;
out_err:
- cfg80211_unlock_rdev(dev);
+ cfg80211_unlock_rdev(rdev);
return err;
}
}
info->user_ptr[0] = rdev;
} 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 (rtnl)
rtnl_unlock();