Commit 67748893 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

nl80211: reduce dumping boilerplate

Consolidate boilerplate code needed for .dumpit
calls operating on netdevs.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 41265714
...@@ -198,6 +198,47 @@ static int nl80211_get_ifidx(struct netlink_callback *cb) ...@@ -198,6 +198,47 @@ static int nl80211_get_ifidx(struct netlink_callback *cb)
return res; 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 */ /* IE validation */
static bool is_valid_ie_attr(const struct nlattr *attr) static bool is_valid_ie_attr(const struct nlattr *attr)
{ {
...@@ -1796,28 +1837,12 @@ static int nl80211_dump_station(struct sk_buff *skb, ...@@ -1796,28 +1837,12 @@ static int nl80211_dump_station(struct sk_buff *skb,
struct cfg80211_registered_device *dev; struct cfg80211_registered_device *dev;
struct net_device *netdev; struct net_device *netdev;
u8 mac_addr[ETH_ALEN]; u8 mac_addr[ETH_ALEN];
int ifidx = cb->args[0];
int sta_idx = cb->args[1]; int sta_idx = cb->args[1];
int err; int err;
if (!ifidx) err = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev);
ifidx = nl80211_get_ifidx(cb); if (err)
if (ifidx < 0) return err;
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;
}
if (!dev->ops->dump_station) { if (!dev->ops->dump_station) {
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
...@@ -1847,9 +1872,7 @@ static int nl80211_dump_station(struct sk_buff *skb, ...@@ -1847,9 +1872,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
cb->args[1] = sta_idx; cb->args[1] = sta_idx;
err = skb->len; err = skb->len;
out_err: out_err:
cfg80211_unlock_rdev(dev); nl80211_finish_netdev_dump(dev);
out_rtnl:
rtnl_unlock();
return err; return err;
} }
...@@ -2169,28 +2192,12 @@ static int nl80211_dump_mpath(struct sk_buff *skb, ...@@ -2169,28 +2192,12 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
struct net_device *netdev; struct net_device *netdev;
u8 dst[ETH_ALEN]; u8 dst[ETH_ALEN];
u8 next_hop[ETH_ALEN]; u8 next_hop[ETH_ALEN];
int ifidx = cb->args[0];
int path_idx = cb->args[1]; int path_idx = cb->args[1];
int err; int err;
if (!ifidx) err = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev);
ifidx = nl80211_get_ifidx(cb); if (err)
if (ifidx < 0) return err;
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;
}
if (!dev->ops->dump_mpath) { if (!dev->ops->dump_mpath) {
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
...@@ -2224,10 +2231,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb, ...@@ -2224,10 +2231,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
cb->args[1] = path_idx; cb->args[1] = path_idx;
err = skb->len; err = skb->len;
out_err: out_err:
cfg80211_unlock_rdev(dev); nl80211_finish_netdev_dump(dev);
out_rtnl:
rtnl_unlock();
return err; return err;
} }
...@@ -3034,25 +3038,12 @@ static int nl80211_dump_scan(struct sk_buff *skb, ...@@ -3034,25 +3038,12 @@ static int nl80211_dump_scan(struct sk_buff *skb,
struct net_device *dev; struct net_device *dev;
struct cfg80211_internal_bss *scan; struct cfg80211_internal_bss *scan;
struct wireless_dev *wdev; struct wireless_dev *wdev;
int ifidx = cb->args[0];
int start = cb->args[1], idx = 0; int start = cb->args[1], idx = 0;
int err; int err;
if (!ifidx) err = nl80211_prepare_netdev_dump(skb, cb, &rdev, &dev);
ifidx = nl80211_get_ifidx(cb); if (err)
if (ifidx < 0) return err;
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;
}
wdev = dev->ieee80211_ptr; wdev = dev->ieee80211_ptr;
...@@ -3068,21 +3059,17 @@ static int nl80211_dump_scan(struct sk_buff *skb, ...@@ -3068,21 +3059,17 @@ static int nl80211_dump_scan(struct sk_buff *skb,
cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh->nlmsg_seq, NLM_F_MULTI,
rdev, wdev, scan) < 0) { rdev, wdev, scan) < 0) {
idx--; idx--;
goto out; break;
} }
} }
out:
spin_unlock_bh(&rdev->bss_lock); spin_unlock_bh(&rdev->bss_lock);
wdev_unlock(wdev); wdev_unlock(wdev);
cb->args[1] = idx; cb->args[1] = idx;
err = skb->len; nl80211_finish_netdev_dump(rdev);
cfg80211_unlock_rdev(rdev);
out_put_netdev:
dev_put(dev);
return err; return skb->len;
} }
static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq, 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, ...@@ -3130,29 +3117,12 @@ static int nl80211_dump_survey(struct sk_buff *skb,
struct survey_info survey; struct survey_info survey;
struct cfg80211_registered_device *dev; struct cfg80211_registered_device *dev;
struct net_device *netdev; struct net_device *netdev;
int ifidx = cb->args[0];
int survey_idx = cb->args[1]; int survey_idx = cb->args[1];
int res; int res;
if (!ifidx) res = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev);
ifidx = nl80211_get_ifidx(cb); if (res)
if (ifidx < 0) return res;
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;
}
if (!dev->ops->dump_survey) { if (!dev->ops->dump_survey) {
res = -EOPNOTSUPP; res = -EOPNOTSUPP;
...@@ -3180,10 +3150,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, ...@@ -3180,10 +3150,7 @@ static int nl80211_dump_survey(struct sk_buff *skb,
cb->args[1] = survey_idx; cb->args[1] = survey_idx;
res = skb->len; res = skb->len;
out_err: out_err:
cfg80211_unlock_rdev(dev); nl80211_finish_netdev_dump(dev);
out_rtnl:
rtnl_unlock();
return res; return res;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment