|
@@ -602,9 +602,12 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
|
|
|
|
|
|
memset(¶ms, 0, sizeof(params));
|
|
|
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto unlock_rtnl;
|
|
|
+
|
|
|
ifindex = dev->ifindex;
|
|
|
type = dev->ieee80211_ptr->iftype;
|
|
|
dev_put(dev);
|
|
@@ -641,17 +644,17 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
|
|
|
if (!err)
|
|
|
flags = &_flags;
|
|
|
}
|
|
|
- rtnl_lock();
|
|
|
+
|
|
|
err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
|
|
|
type, flags, ¶ms);
|
|
|
|
|
|
dev = __dev_get_by_index(&init_net, ifindex);
|
|
|
WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type));
|
|
|
|
|
|
- rtnl_unlock();
|
|
|
-
|
|
|
unlock:
|
|
|
cfg80211_put_dev(drv);
|
|
|
+ unlock_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -674,9 +677,13 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
drv = cfg80211_get_dev_from_info(info);
|
|
|
- if (IS_ERR(drv))
|
|
|
- return PTR_ERR(drv);
|
|
|
+ if (IS_ERR(drv)) {
|
|
|
+ err = PTR_ERR(drv);
|
|
|
+ goto unlock_rtnl;
|
|
|
+ }
|
|
|
|
|
|
if (!drv->ops->add_virtual_intf ||
|
|
|
!(drv->wiphy.interface_modes & (1 << type))) {
|
|
@@ -690,18 +697,17 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
|
|
|
params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
|
|
|
info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
|
|
|
&flags);
|
|
|
err = drv->ops->add_virtual_intf(&drv->wiphy,
|
|
|
nla_data(info->attrs[NL80211_ATTR_IFNAME]),
|
|
|
type, err ? NULL : &flags, ¶ms);
|
|
|
- rtnl_unlock();
|
|
|
-
|
|
|
|
|
|
unlock:
|
|
|
cfg80211_put_dev(drv);
|
|
|
+ unlock_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -711,9 +717,11 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
|
|
|
int ifindex, err;
|
|
|
struct net_device *dev;
|
|
|
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto unlock_rtnl;
|
|
|
ifindex = dev->ifindex;
|
|
|
dev_put(dev);
|
|
|
|
|
@@ -722,12 +730,12 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex);
|
|
|
- rtnl_unlock();
|
|
|
|
|
|
out:
|
|
|
cfg80211_put_dev(drv);
|
|
|
+ unlock_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -779,9 +787,11 @@ 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_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto unlock_rtnl;
|
|
|
|
|
|
if (!drv->ops->get_key) {
|
|
|
err = -EOPNOTSUPP;
|
|
@@ -809,10 +819,8 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
|
|
|
if (mac_addr)
|
|
|
NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
|
|
|
|
|
|
- rtnl_lock();
|
|
|
err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr,
|
|
|
&cookie, get_key_callback);
|
|
|
- rtnl_unlock();
|
|
|
|
|
|
if (err)
|
|
|
goto out;
|
|
@@ -830,6 +838,9 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
|
|
|
out:
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+ unlock_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -858,9 +869,11 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
|
|
|
!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT])
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto unlock_rtnl;
|
|
|
|
|
|
if (info->attrs[NL80211_ATTR_KEY_DEFAULT])
|
|
|
func = drv->ops->set_default_key;
|
|
@@ -872,13 +885,15 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
err = func(&drv->wiphy, dev, key_idx);
|
|
|
- rtnl_unlock();
|
|
|
|
|
|
out:
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+
|
|
|
+ unlock_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -948,22 +963,25 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto unlock_rtnl;
|
|
|
|
|
|
if (!drv->ops->add_key) {
|
|
|
err = -EOPNOTSUPP;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, ¶ms);
|
|
|
- rtnl_unlock();
|
|
|
|
|
|
out:
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+ unlock_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -984,22 +1002,26 @@ 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_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto unlock_rtnl;
|
|
|
|
|
|
if (!drv->ops->del_key) {
|
|
|
err = -EOPNOTSUPP;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr);
|
|
|
- rtnl_unlock();
|
|
|
|
|
|
out:
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+
|
|
|
+ unlock_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -1013,9 +1035,11 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
|
|
|
struct beacon_parameters params;
|
|
|
int haveinfo = 0;
|
|
|
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto unlock_rtnl;
|
|
|
|
|
|
switch (info->genlhdr->cmd) {
|
|
|
case NL80211_CMD_NEW_BEACON:
|
|
@@ -1076,13 +1100,14 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
err = call(&drv->wiphy, dev, ¶ms);
|
|
|
- rtnl_unlock();
|
|
|
|
|
|
out:
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+ unlock_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -1092,22 +1117,25 @@ static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
|
|
|
int err;
|
|
|
struct net_device *dev;
|
|
|
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto unlock_rtnl;
|
|
|
|
|
|
if (!drv->ops->del_beacon) {
|
|
|
err = -EOPNOTSUPP;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
err = drv->ops->del_beacon(&drv->wiphy, dev);
|
|
|
- rtnl_unlock();
|
|
|
|
|
|
out:
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+ unlock_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -1273,14 +1301,18 @@ static int nl80211_dump_station(struct sk_buff *skb,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- netdev = dev_get_by_index(&init_net, ifidx);
|
|
|
- if (!netdev)
|
|
|
- return -ENODEV;
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
+ netdev = __dev_get_by_index(&init_net, ifidx);
|
|
|
+ if (!netdev) {
|
|
|
+ err = -ENODEV;
|
|
|
+ goto out_rtnl;
|
|
|
+ }
|
|
|
|
|
|
dev = cfg80211_get_dev_from_ifindex(ifidx);
|
|
|
if (IS_ERR(dev)) {
|
|
|
err = PTR_ERR(dev);
|
|
|
- goto out_put_netdev;
|
|
|
+ goto out_rtnl;
|
|
|
}
|
|
|
|
|
|
if (!dev->ops->dump_station) {
|
|
@@ -1288,15 +1320,13 @@ static int nl80211_dump_station(struct sk_buff *skb,
|
|
|
goto out_err;
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
-
|
|
|
while (1) {
|
|
|
err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx,
|
|
|
mac_addr, &sinfo);
|
|
|
if (err == -ENOENT)
|
|
|
break;
|
|
|
if (err)
|
|
|
- goto out_err_rtnl;
|
|
|
+ goto out_err;
|
|
|
|
|
|
if (nl80211_send_station(skb,
|
|
|
NETLINK_CB(cb->skb).pid,
|
|
@@ -1312,12 +1342,10 @@ static int nl80211_dump_station(struct sk_buff *skb,
|
|
|
out:
|
|
|
cb->args[1] = sta_idx;
|
|
|
err = skb->len;
|
|
|
- out_err_rtnl:
|
|
|
- rtnl_unlock();
|
|
|
out_err:
|
|
|
cfg80211_put_dev(dev);
|
|
|
- out_put_netdev:
|
|
|
- dev_put(netdev);
|
|
|
+ out_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
|
|
|
return err;
|
|
|
}
|
|
@@ -1338,19 +1366,18 @@ 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_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto out_rtnl;
|
|
|
|
|
|
if (!drv->ops->get_station) {
|
|
|
err = -EOPNOTSUPP;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo);
|
|
|
- rtnl_unlock();
|
|
|
-
|
|
|
if (err)
|
|
|
goto out;
|
|
|
|
|
@@ -1367,10 +1394,12 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
|
|
|
|
|
|
out_free:
|
|
|
nlmsg_free(msg);
|
|
|
-
|
|
|
out:
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+ out_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -1438,9 +1467,11 @@ 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_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto out_rtnl;
|
|
|
|
|
|
err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan);
|
|
|
if (err)
|
|
@@ -1451,15 +1482,16 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, ¶ms);
|
|
|
- rtnl_unlock();
|
|
|
|
|
|
out:
|
|
|
if (params.vlan)
|
|
|
dev_put(params.vlan);
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+ out_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -1501,9 +1533,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
|
|
|
¶ms.station_flags))
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto out_rtnl;
|
|
|
|
|
|
err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan);
|
|
|
if (err)
|
|
@@ -1514,15 +1548,16 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, ¶ms);
|
|
|
- rtnl_unlock();
|
|
|
|
|
|
out:
|
|
|
if (params.vlan)
|
|
|
dev_put(params.vlan);
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+ out_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -1536,22 +1571,25 @@ static int nl80211_del_station(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_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto out_rtnl;
|
|
|
|
|
|
if (!drv->ops->del_station) {
|
|
|
err = -EOPNOTSUPP;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
err = drv->ops->del_station(&drv->wiphy, dev, mac_addr);
|
|
|
- rtnl_unlock();
|
|
|
|
|
|
out:
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+ out_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -1632,14 +1670,18 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- netdev = dev_get_by_index(&init_net, ifidx);
|
|
|
- if (!netdev)
|
|
|
- return -ENODEV;
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
+ netdev = __dev_get_by_index(&init_net, ifidx);
|
|
|
+ if (!netdev) {
|
|
|
+ err = -ENODEV;
|
|
|
+ goto out_rtnl;
|
|
|
+ }
|
|
|
|
|
|
dev = cfg80211_get_dev_from_ifindex(ifidx);
|
|
|
if (IS_ERR(dev)) {
|
|
|
err = PTR_ERR(dev);
|
|
|
- goto out_put_netdev;
|
|
|
+ goto out_rtnl;
|
|
|
}
|
|
|
|
|
|
if (!dev->ops->dump_mpath) {
|
|
@@ -1647,15 +1689,13 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
|
|
|
goto out_err;
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
-
|
|
|
while (1) {
|
|
|
err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx,
|
|
|
dst, next_hop, &pinfo);
|
|
|
if (err == -ENOENT)
|
|
|
break;
|
|
|
if (err)
|
|
|
- goto out_err_rtnl;
|
|
|
+ goto out_err;
|
|
|
|
|
|
if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).pid,
|
|
|
cb->nlh->nlmsg_seq, NLM_F_MULTI,
|
|
@@ -1670,12 +1710,10 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
|
|
|
out:
|
|
|
cb->args[1] = path_idx;
|
|
|
err = skb->len;
|
|
|
- out_err_rtnl:
|
|
|
- rtnl_unlock();
|
|
|
out_err:
|
|
|
cfg80211_put_dev(dev);
|
|
|
- out_put_netdev:
|
|
|
- dev_put(netdev);
|
|
|
+ out_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
|
|
|
return err;
|
|
|
}
|
|
@@ -1697,19 +1735,18 @@ 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_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto out_rtnl;
|
|
|
|
|
|
if (!drv->ops->get_mpath) {
|
|
|
err = -EOPNOTSUPP;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo);
|
|
|
- rtnl_unlock();
|
|
|
-
|
|
|
if (err)
|
|
|
goto out;
|
|
|
|
|
@@ -1726,10 +1763,12 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
|
|
|
|
|
|
out_free:
|
|
|
nlmsg_free(msg);
|
|
|
-
|
|
|
out:
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+ out_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -1750,22 +1789,25 @@ 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_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto out_rtnl;
|
|
|
|
|
|
if (!drv->ops->change_mpath) {
|
|
|
err = -EOPNOTSUPP;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop);
|
|
|
- rtnl_unlock();
|
|
|
|
|
|
out:
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+ out_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
|
|
@@ -1785,22 +1827,25 @@ 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_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto out_rtnl;
|
|
|
|
|
|
if (!drv->ops->add_mpath) {
|
|
|
err = -EOPNOTSUPP;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop);
|
|
|
- rtnl_unlock();
|
|
|
|
|
|
out:
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+ out_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -1814,22 +1859,25 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
|
|
|
if (info->attrs[NL80211_ATTR_MAC])
|
|
|
dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
|
|
|
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto out_rtnl;
|
|
|
|
|
|
if (!drv->ops->del_mpath) {
|
|
|
err = -EOPNOTSUPP;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
err = drv->ops->del_mpath(&drv->wiphy, dev, dst);
|
|
|
- rtnl_unlock();
|
|
|
|
|
|
out:
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+ out_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -1862,22 +1910,25 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
|
|
|
nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
|
|
|
}
|
|
|
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto out_rtnl;
|
|
|
|
|
|
if (!drv->ops->change_bss) {
|
|
|
err = -EOPNOTSUPP;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
err = drv->ops->change_bss(&drv->wiphy, dev, ¶ms);
|
|
|
- rtnl_unlock();
|
|
|
|
|
|
out:
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+ out_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -1972,10 +2023,12 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
|
|
|
struct nlattr *pinfoattr;
|
|
|
struct sk_buff *msg;
|
|
|
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
/* Look up our device */
|
|
|
err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto out_rtnl;
|
|
|
|
|
|
if (!drv->ops->get_mesh_params) {
|
|
|
err = -EOPNOTSUPP;
|
|
@@ -1983,9 +2036,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
|
|
|
}
|
|
|
|
|
|
/* Get the mesh params */
|
|
|
- rtnl_lock();
|
|
|
err = drv->ops->get_mesh_params(&drv->wiphy, dev, &cur_params);
|
|
|
- rtnl_unlock();
|
|
|
if (err)
|
|
|
goto out;
|
|
|
|
|
@@ -2034,13 +2085,16 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
|
|
|
err = genlmsg_unicast(msg, info->snd_pid);
|
|
|
goto out;
|
|
|
|
|
|
-nla_put_failure:
|
|
|
+ nla_put_failure:
|
|
|
genlmsg_cancel(msg, hdr);
|
|
|
err = -EMSGSIZE;
|
|
|
-out:
|
|
|
+ out:
|
|
|
/* Cleanup */
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+ out_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -2087,9 +2141,11 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
|
|
|
parent_attr, nl80211_meshconf_params_policy))
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto out_rtnl;
|
|
|
|
|
|
if (!drv->ops->set_mesh_params) {
|
|
|
err = -EOPNOTSUPP;
|
|
@@ -2136,14 +2192,15 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
|
|
|
nla_get_u16);
|
|
|
|
|
|
/* Apply changes */
|
|
|
- rtnl_lock();
|
|
|
err = drv->ops->set_mesh_params(&drv->wiphy, dev, &cfg, mask);
|
|
|
- rtnl_unlock();
|
|
|
|
|
|
out:
|
|
|
/* cleanup */
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+ out_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -2310,19 +2367,22 @@ static int nl80211_set_mgmt_extra_ie(struct sk_buff *skb,
|
|
|
params.ies_len = nla_len(info->attrs[NL80211_ATTR_IE]);
|
|
|
}
|
|
|
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto out_rtnl;
|
|
|
|
|
|
- if (drv->ops->set_mgmt_extra_ie) {
|
|
|
- rtnl_lock();
|
|
|
+ if (drv->ops->set_mgmt_extra_ie)
|
|
|
err = drv->ops->set_mgmt_extra_ie(&drv->wiphy, dev, ¶ms);
|
|
|
- rtnl_unlock();
|
|
|
- } else
|
|
|
+ else
|
|
|
err = -EOPNOTSUPP;
|
|
|
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+ out_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -2339,9 +2399,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
|
|
enum ieee80211_band band;
|
|
|
size_t ie_len;
|
|
|
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto out_rtnl;
|
|
|
|
|
|
wiphy = &drv->wiphy;
|
|
|
|
|
@@ -2350,11 +2412,9 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- rtnl_lock();
|
|
|
-
|
|
|
if (drv->scan_req) {
|
|
|
err = -EBUSY;
|
|
|
- goto out_unlock;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
|
|
@@ -2362,7 +2422,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
|
|
n_channels++;
|
|
|
if (!n_channels) {
|
|
|
err = -EINVAL;
|
|
|
- goto out_unlock;
|
|
|
+ goto out;
|
|
|
}
|
|
|
} else {
|
|
|
for (band = 0; band < IEEE80211_NUM_BANDS; band++)
|
|
@@ -2376,7 +2436,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
|
|
|
|
|
if (n_ssids > wiphy->max_scan_ssids) {
|
|
|
err = -EINVAL;
|
|
|
- goto out_unlock;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
if (info->attrs[NL80211_ATTR_IE])
|
|
@@ -2390,7 +2450,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
|
|
+ ie_len, GFP_KERNEL);
|
|
|
if (!request) {
|
|
|
err = -ENOMEM;
|
|
|
- goto out_unlock;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
request->channels = (void *)((char *)request + sizeof(*request));
|
|
@@ -2461,11 +2521,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
|
|
drv->scan_req = NULL;
|
|
|
kfree(request);
|
|
|
}
|
|
|
- out_unlock:
|
|
|
- rtnl_unlock();
|
|
|
out:
|
|
|
cfg80211_put_dev(drv);
|
|
|
dev_put(dev);
|
|
|
+ out_rtnl:
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|