aboutsummaryrefslogtreecommitdiff
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-10-04 21:36:35 +0200
committerJohn W. Linville <linville@tuxdriver.com>2010-10-05 13:37:51 -0400
commit4c476991062a0a59523c2bf193f09087f469686a (patch)
treed7342b806c285f7b0987386c3d5157230f858c43 /net/wireless
parentff4c92d85c6f2777d2067f8552e7fefb4d1754ae (diff)
nl80211: use the new genetlink pre/post_doit hooks
This makes nl80211 use the new genetlink pre_doit/post_doit hooks for locking and checking the interface/wiphy index. This significantly reduces the code size and the likelihood of locking errors. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c1733
1 files changed, 531 insertions, 1202 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index fd92b6b7ff0..a96da47d064 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -23,6 +23,11 @@
#include "nl80211.h"
#include "reg.h"
+static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
+ struct genl_info *info);
+static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
+ struct genl_info *info);
+
/* the netlink family */
static struct genl_family nl80211_fam = {
.id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
@@ -31,6 +36,8 @@ static struct genl_family nl80211_fam = {
.version = 1, /* no particular meaning now */
.maxattr = NL80211_ATTR_MAX,
.netnsok = true,
+ .pre_doit = nl80211_pre_doit,
+ .post_doit = nl80211_post_doit,
};
/* internal helper: get rdev and dev */
@@ -704,28 +711,18 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
{
struct sk_buff *msg;
- struct cfg80211_registered_device *dev;
-
- dev = cfg80211_get_dev_from_info(info);
- if (IS_ERR(dev))
- return PTR_ERR(dev);
+ struct cfg80211_registered_device *dev = info->user_ptr[0];
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg)
- goto out_err;
-
- if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0)
- goto out_free;
+ return -ENOMEM;
- cfg80211_unlock_rdev(dev);
+ if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0) {
+ nlmsg_free(msg);
+ return -ENOBUFS;
+ }
return genlmsg_reply(msg, info);
-
- out_free:
- nlmsg_free(msg);
- out_err:
- cfg80211_unlock_rdev(dev);
- return -ENOBUFS;
}
static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = {
@@ -814,24 +811,10 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
- struct net_device *netdev;
- int result;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *netdev = info->user_ptr[1];
- rtnl_lock();
-
- result = get_rdev_dev_by_info_ifindex(info, &rdev, &netdev);
- if (result)
- goto unlock_rtnl;
-
- result = __nl80211_set_channel(rdev, netdev->ieee80211_ptr, info);
-
- dev_put(netdev);
- cfg80211_unlock_rdev(rdev);
- unlock_rtnl:
- rtnl_unlock();
-
- return result;
+ return __nl80211_set_channel(rdev, netdev->ieee80211_ptr, info);
}
static int nl80211_set_wds_peer(struct sk_buff *skb, struct genl_info *info)
@@ -893,8 +876,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
u32 frag_threshold = 0, rts_threshold = 0;
u8 coverage_class = 0;
- rtnl_lock();
-
/*
* Try to find the wiphy and netdev. Normally this
* function shouldn't need the netdev, but this is
@@ -921,8 +902,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
rdev = __cfg80211_rdev_from_info(info);
if (IS_ERR(rdev)) {
mutex_unlock(&cfg80211_mutex);
- result = PTR_ERR(rdev);
- goto unlock;
+ return PTR_ERR(rdev);
}
wdev = NULL;
netdev = NULL;
@@ -1104,8 +1084,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
mutex_unlock(&rdev->mtx);
if (netdev)
dev_put(netdev);
- unlock:
- rtnl_unlock();
return result;
}
@@ -1185,33 +1163,20 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
{
struct sk_buff *msg;
- struct cfg80211_registered_device *dev;
- struct net_device *netdev;
- int err;
-
- err = get_rdev_dev_by_info_ifindex(info, &dev, &netdev);
- if (err)
- return err;
+ struct cfg80211_registered_device *dev = info->user_ptr[0];
+ struct net_device *netdev = info->user_ptr[1];
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg)
- goto out_err;
+ return -ENOMEM;
if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0,
- dev, netdev) < 0)
- goto out_free;
-
- dev_put(netdev);
- cfg80211_unlock_rdev(dev);
+ dev, netdev) < 0) {
+ nlmsg_free(msg);
+ return -ENOBUFS;
+ }
return genlmsg_reply(msg, info);
-
- out_free:
- nlmsg_free(msg);
- out_err:
- dev_put(netdev);
- cfg80211_unlock_rdev(dev);
- return -ENOBUFS;
}
static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
@@ -1271,39 +1236,29 @@ static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct vif_params params;
int err;
enum nl80211_iftype otype, ntype;
- struct net_device *dev;
+ struct net_device *dev = info->user_ptr[1];
u32 _flags, *flags = NULL;
bool change = false;
memset(&params, 0, sizeof(params));
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto unlock_rtnl;
-
otype = ntype = dev->ieee80211_ptr->iftype;
if (info->attrs[NL80211_ATTR_IFTYPE]) {
ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
if (otype != ntype)
change = true;
- if (ntype > NL80211_IFTYPE_MAX) {
- err = -EINVAL;
- goto unlock;
- }
+ if (ntype > NL80211_IFTYPE_MAX)
+ return -EINVAL;
}
if (info->attrs[NL80211_ATTR_MESH_ID]) {
- if (ntype != NL80211_IFTYPE_MESH_POINT) {
- err = -EINVAL;
- goto unlock;
- }
+ if (ntype != NL80211_IFTYPE_MESH_POINT)
+ return -EINVAL;
params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
change = true;
@@ -1314,20 +1269,18 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
change = true;
err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
if (err)
- goto unlock;
+ return err;
} else {
params.use_4addr = -1;
}
if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
- if (ntype != NL80211_IFTYPE_MONITOR) {
- err = -EINVAL;
- goto unlock;
- }
+ if (ntype != NL80211_IFTYPE_MONITOR)
+ return -EINVAL;
err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
&_flags);
if (err)
- goto unlock;
+ return err;
flags = &_flags;
change = true;
@@ -1341,17 +1294,12 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
if (!err && params.use_4addr != -1)
dev->ieee80211_ptr->use_4addr = params.use_4addr;
- unlock:
- dev_put(dev);
- cfg80211_unlock_rdev(rdev);
- unlock_rtnl:
- rtnl_unlock();
return err;
}
static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct vif_params params;
int err;
enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
@@ -1368,19 +1316,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}
- rtnl_lock();
-
- rdev = cfg80211_get_dev_from_info(info);
- if (IS_ERR(rdev)) {
- err = PTR_ERR(rdev);
- goto unlock_rtnl;
- }
-
if (!rdev->ops->add_virtual_intf ||
- !(rdev->wiphy.interface_modes & (1 << type))) {
- err = -EOPNOTSUPP;
- goto unlock;
- }
+ !(rdev->wiphy.interface_modes & (1 << type)))
+ return -EOPNOTSUPP;
if (type == NL80211_IFTYPE_MESH_POINT &&
info->attrs[NL80211_ATTR_MESH_ID]) {
@@ -1392,7 +1330,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
if (err)
- goto unlock;
+ return err;
}
err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
@@ -1402,38 +1340,18 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
nla_data(info->attrs[NL80211_ATTR_IFNAME]),
type, err ? NULL : &flags, &params);
- unlock:
- cfg80211_unlock_rdev(rdev);
- unlock_rtnl:
- rtnl_unlock();
return err;
}
static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
- int err;
- struct net_device *dev;
-
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto unlock_rtnl;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
- if (!rdev->ops->del_virtual_intf) {
- err = -EOPNOTSUPP;
- goto out;
- }
-
- err = rdev->ops->del_virtual_intf(&rdev->wiphy, dev);
+ if (!rdev->ops->del_virtual_intf)
+ return -EOPNOTSUPP;
- out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- unlock_rtnl:
- rtnl_unlock();
- return err;
+ return rdev->ops->del_virtual_intf(&rdev->wiphy, dev);
}
struct get_key_cookie {
@@ -1486,9 +1404,9 @@ static void get_key_callback(void *c, struct key_params *params)
static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
int err;
- struct net_device *dev;
+ struct net_device *dev = info->user_ptr[1];
u8 key_idx = 0;
u8 *mac_addr = NULL;
struct get_key_cookie cookie = {
@@ -1506,30 +1424,17 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_MAC])
mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto unlock_rtnl;
-
- if (!rdev->ops->get_key) {
- err = -EOPNOTSUPP;
- goto out;
- }
+ if (!rdev->ops->get_key)
+ return -EOPNOTSUPP;
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!msg) {
- err = -ENOMEM;
- goto out;
- }
+ if (!msg)
+ return -ENOMEM;
hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
NL80211_CMD_NEW_KEY);
-
- if (IS_ERR(hdr)) {
- err = PTR_ERR(hdr);
- goto free_msg;
- }
+ if (IS_ERR(hdr))
+ return PTR_ERR(hdr);
cookie.msg = msg;
cookie.idx = key_idx;
@@ -1549,28 +1454,21 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
goto nla_put_failure;
genlmsg_end(msg, hdr);
- err = genlmsg_reply(msg, info);
- goto out;
+ return genlmsg_reply(msg, info);
nla_put_failure:
err = -ENOBUFS;
free_msg:
nlmsg_free(msg);
- out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- unlock_rtnl:
- rtnl_unlock();
-
return err;
}
static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct key_parse key;
int err;
- struct net_device *dev;
+ struct net_device *dev = info->user_ptr[1];
int (*func)(struct wiphy *wiphy, struct net_device *netdev,
u8 key_index);
@@ -1585,21 +1483,13 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
if (!key.def && !key.defmgmt)
return -EINVAL;
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto unlock_rtnl;
-
if (key.def)
func = rdev->ops->set_default_key;
else
func = rdev->ops->set_default_mgmt_key;
- if (!func) {
- err = -EOPNOTSUPP;
- goto out;
- }
+ if (!func)
+ return -EOPNOTSUPP;
wdev_lock(dev->ieee80211_ptr);
err = nl80211_key_allowed(dev->ieee80211_ptr);
@@ -1616,21 +1506,14 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
#endif
wdev_unlock(dev->ieee80211_ptr);
- out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
-
- unlock_rtnl:
- rtnl_unlock();
-
return err;
}
static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
int err;
- struct net_device *dev;
+ struct net_device *dev = info->user_ptr[1];
struct key_parse key;
u8 *mac_addr = NULL;
@@ -1644,21 +1527,11 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_MAC])
mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto unlock_rtnl;
-
- if (!rdev->ops->add_key) {
- err = -EOPNOTSUPP;
- goto out;
- }
+ if (!rdev->ops->add_key)
+ return -EOPNOTSUPP;
- if (cfg80211_validate_key_settings(rdev, &key.p, key.idx, mac_addr)) {
- err = -EINVAL;
- goto out;
- }
+ if (cfg80211_validate_key_settings(rdev, &key.p, key.idx, mac_addr))
+ return -EINVAL;
wdev_lock(dev->ieee80211_ptr);
err = nl80211_key_allowed(dev->ieee80211_ptr);
@@ -1667,20 +1540,14 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
mac_addr, &key.p);
wdev_unlock(dev->ieee80211_ptr);
- out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- unlock_rtnl:
- rtnl_unlock();
-
return err;
}
static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
int err;
- struct net_device *dev;
+ struct net_device *dev = info->user_ptr[1];
u8 *mac_addr = NULL;
struct key_parse key;
@@ -1691,16 +1558,8 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_MAC])
mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto unlock_rtnl;
-
- if (!rdev->ops->del_key) {
- err = -EOPNOTSUPP;
- goto out;
- }
+ if (!rdev->ops->del_key)
+ return -EOPNOTSUPP;
wdev_lock(dev->ieee80211_ptr);
err = nl80211_key_allowed(dev->ieee80211_ptr);
@@ -1717,13 +1576,6 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
#endif
wdev_unlock(dev->ieee80211_ptr);
- out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
-
- unlock_rtnl:
- rtnl_unlock();
-
return err;
}
@@ -1731,36 +1583,25 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
{
int (*call)(struct wiphy *wiphy, struct net_device *dev,
struct beacon_parameters *info);
- struct cfg80211_registered_device *rdev;
- int err;
- struct net_device *dev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
struct beacon_parameters params;
int haveinfo = 0;
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL]))
return -EINVAL;
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto unlock_rtnl;
-
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
- err = -EOPNOTSUPP;
- goto out;
- }
+ dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ return -EOPNOTSUPP;
switch (info->genlhdr->cmd) {
case NL80211_CMD_NEW_BEACON:
/* these are required for NEW_BEACON */
if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
!info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
- !info->attrs[NL80211_ATTR_BEACON_HEAD]) {
- err = -EINVAL;
- goto out;
- }
+ !info->attrs[NL80211_ATTR_BEACON_HEAD])
+ return -EINVAL;
call = rdev->ops->add_beacon;
break;
@@ -1769,14 +1610,11 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
break;
default:
WARN_ON(1);
- err = -EOPNOTSUPP;
- goto out;
+ return -EOPNOTSUPP;
}
- if (!call) {
- err = -EOPNOTSUPP;
- goto out;
- }
+ if (!call)
+ return -EOPNOTSUPP;
memset(&params, 0, sizeof(params));
@@ -1806,53 +1644,25 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
haveinfo = 1;
}
- if (!haveinfo) {
- err = -EINVAL;
- goto out;
- }
-
- err = call(&rdev->wiphy, dev, &params);
-
- out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- unlock_rtnl:
- rtnl_unlock();
+ if (!haveinfo)
+ return -EINVAL;
- return err;
+ return call(&rdev->wiphy, dev, &params);
}
static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
- int err;
- struct net_device *dev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto unlock_rtnl;
-
- if (!rdev->ops->del_beacon) {
- err = -EOPNOTSUPP;
- goto out;
- }
+ if (!rdev->ops->del_beacon)
+ return -EOPNOTSUPP;
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
- err = -EOPNOTSUPP;
- goto out;
- }
- err = rdev->ops->del_beacon(&rdev->wiphy, dev);
-
- out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- unlock_rtnl:
- rtnl_unlock();
+ dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ return -EOPNOTSUPP;
- return err;
+ return rdev->ops->del_beacon(&rdev->wiphy, dev);
}
static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
@@ -2049,12 +1859,12 @@ static int nl80211_dump_station(struct sk_buff *skb,
static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
- int err;
- struct net_device *dev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
struct station_info sinfo;
struct sk_buff *msg;
u8 *mac_addr = NULL;
+ int err;
memset(&sinfo, 0, sizeof(sinfo));
@@ -2063,41 +1873,24 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto out_rtnl;
-
- if (!rdev->ops->get_station) {
- err = -EOPNOTSUPP;
- goto out;
- }
+ if (!rdev->ops->get_station)
+ return -EOPNOTSUPP;
err = rdev->ops->get_station(&rdev->wiphy, dev, mac_addr, &sinfo);
if (err)
- goto out;
+ return err;
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg)
- goto out;
+ return -ENOMEM;
if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
- dev, mac_addr, &sinfo) < 0)
- goto out_free;
-
- err = genlmsg_reply(msg, info);
- goto out;
-
- out_free:
- nlmsg_free(msg);
- out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- out_rtnl:
- rtnl_unlock();
+ dev, mac_addr, &sinfo) < 0) {
+ nlmsg_free(msg);
+ return -ENOBUFS;
+ }
- return err;
+ return genlmsg_reply(msg, info);
}
/*
@@ -2127,9 +1920,9 @@ static int get_vlan(struct genl_info *info,
static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
int err;
- struct net_device *dev;
+ struct net_device *dev = info->user_ptr[1];
struct station_parameters params;
u8 *mac_addr = NULL;
@@ -2167,12 +1960,6 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
params.plink_action =
nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto out_rtnl;
-
err = get_vlan(info, rdev, &params.vlan);
if (err)
goto out;
@@ -2234,19 +2021,15 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
out:
if (params.vlan)
dev_put(params.vlan);
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- out_rtnl:
- rtnl_unlock();
return err;
}
static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
int err;
- struct net_device *dev;
+ struct net_device *dev = info->user_ptr[1];
struct station_parameters params;
u8 *mac_addr = NULL;
@@ -2283,18 +2066,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
if (parse_station_flags(info, &params))
return -EINVAL;
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto out_rtnl;
-
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
- err = -EINVAL;
- goto out;
- }
+ dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ return -EINVAL;
err = get_vlan(info, rdev, &params.vlan);
if (err)
@@ -2318,52 +2093,28 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
out:
if (params.vlan)
dev_put(params.vlan);
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- out_rtnl:
- rtnl_unlock();
-
return err;
}
static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
- int err;
- struct net_device *dev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
u8 *mac_addr = NULL;
if (info->attrs[NL80211_ATTR_MAC])
mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto out_rtnl;
-
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
- err = -EINVAL;
- goto out;
- }
-
- if (!rdev->ops->del_station) {
- err = -EOPNOTSUPP;
- goto out;
- }
-
- err = rdev->ops->del_station(&rdev->wiphy, dev, mac_addr);
+ dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ return -EINVAL;
- out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- out_rtnl:
- rtnl_unlock();
+ if (!rdev->ops->del_station)
+ return -EOPNOTSUPP;
- return err;
+ return rdev->ops->del_station(&rdev->wiphy, dev, mac_addr);
}
static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq,
@@ -2490,9 +2241,9 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
int err;
- struct net_device *dev;
+ struct net_device *dev = info->user_ptr[1];
struct mpath_info pinfo;
struct sk_buff *msg;
u8 *dst = NULL;
@@ -2505,53 +2256,33 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto out_rtnl;
-
- if (!rdev->ops->get_mpath) {
- err = -EOPNOTSUPP;
- goto out;
- }
+ if (!rdev->ops->get_mpath)
+ return -EOPNOTSUPP;
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
- err = -EOPNOTSUPP;
- goto out;
- }
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
+ return -EOPNOTSUPP;
err = rdev->ops->get_mpath(&rdev->wiphy, dev, dst, next_hop, &pinfo);
if (err)
- goto out;
+ return err;
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg)
- goto out;
+ return -ENOMEM;
if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0,
- dev, dst, next_hop, &pinfo) < 0)
- goto out_free;
-
- err = genlmsg_reply(msg, info);
- goto out;
-
- out_free:
- nlmsg_free(msg);
- out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- out_rtnl:
- rtnl_unlock();
+ dev, dst, next_hop, &pinfo) < 0) {
+ nlmsg_free(msg);
+ return -ENOBUFS;
+ }
- return err;
+ return genlmsg_reply(msg, info);
}
static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
- int err;
- struct net_device *dev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
u8 *dst = NULL;
u8 *next_hop = NULL;
@@ -2564,42 +2295,22 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto out_rtnl;
-
- if (!rdev->ops->change_mpath) {
- err = -EOPNOTSUPP;
- goto out;
- }
-
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
- err = -EOPNOTSUPP;
- goto out;
- }
-
- if (!netif_running(dev)) {
- err = -ENETDOWN;
- goto out;
- }
+ if (!rdev->ops->change_mpath)
+ return -EOPNOTSUPP;
- err = rdev->ops->change_mpath(&rdev->wiphy, dev, dst, next_hop);
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
+ return -EOPNOTSUPP;
- out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- out_rtnl:
- rtnl_unlock();
+ if (!netif_running(dev))
+ return -ENETDOWN;
- return err;
+ return rdev->ops->change_mpath(&rdev->wiphy, dev, dst, next_hop);
}
+
static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
- int err;
- struct net_device *dev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
u8 *dst = NULL;
u8 *next_hop = NULL;
@@ -2612,75 +2323,37 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto out_rtnl;
-
- if (!rdev->ops->add_mpath) {
- err = -EOPNOTSUPP;
- goto out;
- }
-
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
- err = -EOPNOTSUPP;
- goto out;
- }
-
- if (!netif_running(dev)) {
- err = -ENETDOWN;
- goto out;
- }
+ if (!rdev->ops->add_mpath)
+ return -EOPNOTSUPP;
- err = rdev->ops->add_mpath(&rdev->wiphy, dev, dst, next_hop);
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
+ return -EOPNOTSUPP;
- out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- out_rtnl:
- rtnl_unlock();
+ if (!netif_running(dev))
+ return -ENETDOWN;
- return err;
+ return rdev->ops->add_mpath(&rdev->wiphy, dev, dst, next_hop);
}
static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
- int err;
- struct net_device *dev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
u8 *dst = NULL;
if (info->attrs[NL80211_ATTR_MAC])
dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto out_rtnl;
-
- if (!rdev->ops->del_mpath) {
- err = -EOPNOTSUPP;
- goto out;
- }
-
- err = rdev->ops->del_mpath(&rdev->wiphy, dev, dst);
-
- out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- out_rtnl:
- rtnl_unlock();
+ if (!rdev->ops->del_mpath)
+ return -EOPNOTSUPP;
- return err;
+ return rdev->ops->del_mpath(&rdev->wiphy, dev, dst);
}
static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
- int err;
- struct net_device *dev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
struct bss_parameters params;
memset(&params, 0, sizeof(params));
@@ -2708,32 +2381,14 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_AP_ISOLATE])
params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]);
- rtnl_lock();
-
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto out_rtnl;
-
- if (!rdev->ops->change_bss) {
- err = -EOPNOTSUPP;
- goto out;
- }
+ if (!rdev->ops->change_bss)
+ return -EOPNOTSUPP;
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
- err = -EOPNOTSUPP;
- goto out;
- }
-
- err = rdev->ops->change_bss(&rdev->wiphy, dev, &params);
-
- out:
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- out_rtnl:
- rtnl_unlock();
+ dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ return -EOPNOTSUPP;
- return err;
+ return rdev->ops->change_bss(&rdev->wiphy, dev, &params);
}
static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
@@ -2812,37 +2467,26 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
static int nl80211_get_mesh_params(struct sk_buff *skb,
struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct mesh_config cur_params;
int err;
- struct net_device *dev;
+ struct net_device *dev = info->user_ptr[1];
void *hdr;
struct nlattr *pinfoattr;
struct sk_buff *msg;
- rtnl_lock();
-
- /* Look up our device */
- err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
- if (err)
- goto out_rtnl;
-
- if (!rdev->ops->get_mesh_params) {
- err = -EOPNOTSUPP;
- goto out;
- }
+ if (!rdev->ops->get_mesh_params)
+ return -EOPNOTSUPP;
/* Get the mesh params */
err = rdev->ops->get_mesh_params(&rdev->wiphy, dev, &cur_params);
if (err)
- goto out;
+ return err;
/* Draw up a netlink message to send back */
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!msg) {
- err = -ENOBUFS;
- goto out;
- }
+ if (!msg)
+ return -ENOMEM;
hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
NL80211_CMD_GET_MESH_PARAMS);
if (!hdr)
@@ -2881,21 +2525,12 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
cur_params.dot11MeshHWMPRootMode);
nla_nest_end(msg, pinfoattr);
genlmsg_end(msg, hdr);
- err = genlmsg_reply(msg, info);
- goto out;
+ return genlmsg_reply(msg, info);
nla_put_failure:
genlmsg_cancel(msg, hdr);
nlmsg_free(msg);
- err = -EMSGSIZE;
- out:
- /* Cleanup */
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- out_rtnl:
- rtnl_unlock();
-
- return err;
+ return -ENOBUFS;
}
#define FILL_IN_MESH_PARAM_IF_SET(table, cfg, param, mask, attr_num, nla_fn) \
@@ -2925,10 +2560,9 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
{
- int err;
u32 mask;
- struct cfg80211_registered_device *rdev;
- struct net_device *dev;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
struct mesh_config cfg;
struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
struct nlattr *parent_attr;
@@ -2940,16 +2574,8 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
parent_attr, nl80211_meshconf_params_policy))
return -EINVAL;
- rtnl_lock();