|
@@ -198,6 +198,47 @@ static int nl80211_get_ifidx(struct netlink_callback *cb)
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
+static int nl80211_prepare_netdev_dump(struct sk_buff *skb,
|
|
|
+ struct netlink_callback *cb,
|
|
|
+ struct cfg80211_registered_device **rdev,
|
|
|
+ struct net_device **dev)
|
|
|
+{
|
|
|
+ int ifidx = cb->args[0];
|
|
|
+ int err;
|
|
|
+
|
|
|
+ if (!ifidx)
|
|
|
+ ifidx = nl80211_get_ifidx(cb);
|
|
|
+ if (ifidx < 0)
|
|
|
+ return ifidx;
|
|
|
+
|
|
|
+ cb->args[0] = ifidx;
|
|
|
+
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
+ *dev = __dev_get_by_index(sock_net(skb->sk), ifidx);
|
|
|
+ if (!*dev) {
|
|
|
+ err = -ENODEV;
|
|
|
+ goto out_rtnl;
|
|
|
+ }
|
|
|
+
|
|
|
+ *rdev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
|
|
|
+ if (IS_ERR(dev)) {
|
|
|
+ err = PTR_ERR(dev);
|
|
|
+ goto out_rtnl;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ out_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+static void nl80211_finish_netdev_dump(struct cfg80211_registered_device *rdev)
|
|
|
+{
|
|
|
+ cfg80211_unlock_rdev(rdev);
|
|
|
+ rtnl_unlock();
|
|
|
+}
|
|
|
+
|
|
|
/* IE validation */
|
|
|
static bool is_valid_ie_attr(const struct nlattr *attr)
|
|
|
{
|
|
@@ -1796,28 +1837,12 @@ static int nl80211_dump_station(struct sk_buff *skb,
|
|
|
struct cfg80211_registered_device *dev;
|
|
|
struct net_device *netdev;
|
|
|
u8 mac_addr[ETH_ALEN];
|
|
|
- int ifidx = cb->args[0];
|
|
|
int sta_idx = cb->args[1];
|
|
|
int err;
|
|
|
|
|
|
- if (!ifidx)
|
|
|
- ifidx = nl80211_get_ifidx(cb);
|
|
|
- if (ifidx < 0)
|
|
|
- return ifidx;
|
|
|
-
|
|
|
- rtnl_lock();
|
|
|
-
|
|
|
- netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
|
|
|
- if (!netdev) {
|
|
|
- err = -ENODEV;
|
|
|
- goto out_rtnl;
|
|
|
- }
|
|
|
-
|
|
|
- dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
|
|
|
- if (IS_ERR(dev)) {
|
|
|
- err = PTR_ERR(dev);
|
|
|
- goto out_rtnl;
|
|
|
- }
|
|
|
+ err = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
|
|
|
if (!dev->ops->dump_station) {
|
|
|
err = -EOPNOTSUPP;
|
|
@@ -1847,9 +1872,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
|
|
|
cb->args[1] = sta_idx;
|
|
|
err = skb->len;
|
|
|
out_err:
|
|
|
- cfg80211_unlock_rdev(dev);
|
|
|
- out_rtnl:
|
|
|
- rtnl_unlock();
|
|
|
+ nl80211_finish_netdev_dump(dev);
|
|
|
|
|
|
return err;
|
|
|
}
|
|
@@ -2169,28 +2192,12 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
|
|
|
struct net_device *netdev;
|
|
|
u8 dst[ETH_ALEN];
|
|
|
u8 next_hop[ETH_ALEN];
|
|
|
- int ifidx = cb->args[0];
|
|
|
int path_idx = cb->args[1];
|
|
|
int err;
|
|
|
|
|
|
- if (!ifidx)
|
|
|
- ifidx = nl80211_get_ifidx(cb);
|
|
|
- if (ifidx < 0)
|
|
|
- return ifidx;
|
|
|
-
|
|
|
- rtnl_lock();
|
|
|
-
|
|
|
- netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
|
|
|
- if (!netdev) {
|
|
|
- err = -ENODEV;
|
|
|
- goto out_rtnl;
|
|
|
- }
|
|
|
-
|
|
|
- dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
|
|
|
- if (IS_ERR(dev)) {
|
|
|
- err = PTR_ERR(dev);
|
|
|
- goto out_rtnl;
|
|
|
- }
|
|
|
+ err = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
|
|
|
if (!dev->ops->dump_mpath) {
|
|
|
err = -EOPNOTSUPP;
|
|
@@ -2224,10 +2231,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
|
|
|
cb->args[1] = path_idx;
|
|
|
err = skb->len;
|
|
|
out_err:
|
|
|
- cfg80211_unlock_rdev(dev);
|
|
|
- out_rtnl:
|
|
|
- rtnl_unlock();
|
|
|
-
|
|
|
+ nl80211_finish_netdev_dump(dev);
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -3034,25 +3038,12 @@ static int nl80211_dump_scan(struct sk_buff *skb,
|
|
|
struct net_device *dev;
|
|
|
struct cfg80211_internal_bss *scan;
|
|
|
struct wireless_dev *wdev;
|
|
|
- int ifidx = cb->args[0];
|
|
|
int start = cb->args[1], idx = 0;
|
|
|
int err;
|
|
|
|
|
|
- if (!ifidx)
|
|
|
- ifidx = nl80211_get_ifidx(cb);
|
|
|
- if (ifidx < 0)
|
|
|
- return ifidx;
|
|
|
- cb->args[0] = ifidx;
|
|
|
-
|
|
|
- dev = dev_get_by_index(sock_net(skb->sk), ifidx);
|
|
|
- if (!dev)
|
|
|
- return -ENODEV;
|
|
|
-
|
|
|
- rdev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
|
|
|
- if (IS_ERR(rdev)) {
|
|
|
- err = PTR_ERR(rdev);
|
|
|
- goto out_put_netdev;
|
|
|
- }
|
|
|
+ err = nl80211_prepare_netdev_dump(skb, cb, &rdev, &dev);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
|
|
|
wdev = dev->ieee80211_ptr;
|
|
|
|
|
@@ -3068,21 +3059,17 @@ static int nl80211_dump_scan(struct sk_buff *skb,
|
|
|
cb->nlh->nlmsg_seq, NLM_F_MULTI,
|
|
|
rdev, wdev, scan) < 0) {
|
|
|
idx--;
|
|
|
- goto out;
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- out:
|
|
|
spin_unlock_bh(&rdev->bss_lock);
|
|
|
wdev_unlock(wdev);
|
|
|
|
|
|
cb->args[1] = idx;
|
|
|
- err = skb->len;
|
|
|
- cfg80211_unlock_rdev(rdev);
|
|
|
- out_put_netdev:
|
|
|
- dev_put(dev);
|
|
|
+ nl80211_finish_netdev_dump(rdev);
|
|
|
|
|
|
- return err;
|
|
|
+ return skb->len;
|
|
|
}
|
|
|
|
|
|
static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq,
|
|
@@ -3130,29 +3117,12 @@ static int nl80211_dump_survey(struct sk_buff *skb,
|
|
|
struct survey_info survey;
|
|
|
struct cfg80211_registered_device *dev;
|
|
|
struct net_device *netdev;
|
|
|
- int ifidx = cb->args[0];
|
|
|
int survey_idx = cb->args[1];
|
|
|
int res;
|
|
|
|
|
|
- if (!ifidx)
|
|
|
- ifidx = nl80211_get_ifidx(cb);
|
|
|
- if (ifidx < 0)
|
|
|
- return ifidx;
|
|
|
- cb->args[0] = ifidx;
|
|
|
-
|
|
|
- rtnl_lock();
|
|
|
-
|
|
|
- netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
|
|
|
- if (!netdev) {
|
|
|
- res = -ENODEV;
|
|
|
- goto out_rtnl;
|
|
|
- }
|
|
|
-
|
|
|
- dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
|
|
|
- if (IS_ERR(dev)) {
|
|
|
- res = PTR_ERR(dev);
|
|
|
- goto out_rtnl;
|
|
|
- }
|
|
|
+ res = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev);
|
|
|
+ if (res)
|
|
|
+ return res;
|
|
|
|
|
|
if (!dev->ops->dump_survey) {
|
|
|
res = -EOPNOTSUPP;
|
|
@@ -3180,10 +3150,7 @@ static int nl80211_dump_survey(struct sk_buff *skb,
|
|
|
cb->args[1] = survey_idx;
|
|
|
res = skb->len;
|
|
|
out_err:
|
|
|
- cfg80211_unlock_rdev(dev);
|
|
|
- out_rtnl:
|
|
|
- rtnl_unlock();
|
|
|
-
|
|
|
+ nl80211_finish_netdev_dump(dev);
|
|
|
return res;
|
|
|
}
|
|
|
|