aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-10-04 15:36:35 -0400
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 fd92b6b7ff04..a96da47d0640 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -23,6 +23,11 @@
23#include "nl80211.h" 23#include "nl80211.h"
24#include "reg.h" 24#include "reg.h"
25 25
26static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
27 struct genl_info *info);
28static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
29 struct genl_info *info);
30
26/* the netlink family */ 31/* the netlink family */
27static struct genl_family nl80211_fam = { 32static struct genl_family nl80211_fam = {
28 .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */ 33 .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
@@ -31,6 +36,8 @@ static struct genl_family nl80211_fam = {
31 .version = 1, /* no particular meaning now */ 36 .version = 1, /* no particular meaning now */
32 .maxattr = NL80211_ATTR_MAX, 37 .maxattr = NL80211_ATTR_MAX,
33 .netnsok = true, 38 .netnsok = true,
39 .pre_doit = nl80211_pre_doit,
40 .post_doit = nl80211_post_doit,
34}; 41};
35 42
36/* internal helper: get rdev and dev */ 43/* internal helper: get rdev and dev */
@@ -704,28 +711,18 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
704static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) 711static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
705{ 712{
706 struct sk_buff *msg; 713 struct sk_buff *msg;
707 struct cfg80211_registered_device *dev; 714 struct cfg80211_registered_device *dev = info->user_ptr[0];
708
709 dev = cfg80211_get_dev_from_info(info);
710 if (IS_ERR(dev))
711 return PTR_ERR(dev);
712 715
713 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 716 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
714 if (!msg) 717 if (!msg)
715 goto out_err; 718 return -ENOMEM;
716
717 if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0)
718 goto out_free;
719 719
720 cfg80211_unlock_rdev(dev); 720 if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0) {
721 nlmsg_free(msg);
722 return -ENOBUFS;
723 }
721 724
722 return genlmsg_reply(msg, info); 725 return genlmsg_reply(msg, info);
723
724 out_free:
725 nlmsg_free(msg);
726 out_err:
727 cfg80211_unlock_rdev(dev);
728 return -ENOBUFS;
729} 726}
730 727
731static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = { 728static 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,
814 811
815static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info) 812static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info)
816{ 813{
817 struct cfg80211_registered_device *rdev; 814 struct cfg80211_registered_device *rdev = info->user_ptr[0];
818 struct net_device *netdev; 815 struct net_device *netdev = info->user_ptr[1];
819 int result;
820 816
821 rtnl_lock(); 817 return __nl80211_set_channel(rdev, netdev->ieee80211_ptr, info);
822
823 result = get_rdev_dev_by_info_ifindex(info, &rdev, &netdev);
824 if (result)
825 goto unlock_rtnl;
826
827 result = __nl80211_set_channel(rdev, netdev->ieee80211_ptr, info);
828
829 dev_put(netdev);
830 cfg80211_unlock_rdev(rdev);
831 unlock_rtnl:
832 rtnl_unlock();
833
834 return result;
835} 818}
836 819
837static int nl80211_set_wds_peer(struct sk_buff *skb, struct genl_info *info) 820static 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)
893 u32 frag_threshold = 0, rts_threshold = 0; 876 u32 frag_threshold = 0, rts_threshold = 0;
894 u8 coverage_class = 0; 877 u8 coverage_class = 0;
895 878
896 rtnl_lock();
897
898 /* 879 /*
899 * Try to find the wiphy and netdev. Normally this 880 * Try to find the wiphy and netdev. Normally this
900 * function shouldn't need the netdev, but this is 881 * 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)
921 rdev = __cfg80211_rdev_from_info(info); 902 rdev = __cfg80211_rdev_from_info(info);
922 if (IS_ERR(rdev)) { 903 if (IS_ERR(rdev)) {
923 mutex_unlock(&cfg80211_mutex); 904 mutex_unlock(&cfg80211_mutex);
924 result = PTR_ERR(rdev); 905 return PTR_ERR(rdev);
925 goto unlock;
926 } 906 }
927 wdev = NULL; 907 wdev = NULL;
928 netdev = NULL; 908 netdev = NULL;
@@ -1104,8 +1084,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
1104 mutex_unlock(&rdev->mtx); 1084 mutex_unlock(&rdev->mtx);
1105 if (netdev) 1085 if (netdev)
1106 dev_put(netdev); 1086 dev_put(netdev);
1107 unlock:
1108 rtnl_unlock();
1109 return result; 1087 return result;
1110} 1088}
1111 1089
@@ -1185,33 +1163,20 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
1185static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info) 1163static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
1186{ 1164{
1187 struct sk_buff *msg; 1165 struct sk_buff *msg;
1188 struct cfg80211_registered_device *dev; 1166 struct cfg80211_registered_device *dev = info->user_ptr[0];
1189 struct net_device *netdev; 1167 struct net_device *netdev = info->user_ptr[1];
1190 int err;
1191
1192 err = get_rdev_dev_by_info_ifindex(info, &dev, &netdev);
1193 if (err)
1194 return err;
1195 1168
1196 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1169 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1197 if (!msg) 1170 if (!msg)
1198 goto out_err; 1171 return -ENOMEM;
1199 1172
1200 if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, 1173 if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0,
1201 dev, netdev) < 0) 1174 dev, netdev) < 0) {
1202 goto out_free; 1175 nlmsg_free(msg);
1203 1176 return -ENOBUFS;
1204 dev_put(netdev); 1177 }
1205 cfg80211_unlock_rdev(dev);
1206 1178
1207 return genlmsg_reply(msg, info); 1179 return genlmsg_reply(msg, info);
1208
1209 out_free:
1210 nlmsg_free(msg);
1211 out_err:
1212 dev_put(netdev);
1213 cfg80211_unlock_rdev(dev);
1214 return -ENOBUFS;
1215} 1180}
1216 1181
1217static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = { 1182static 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,
1271 1236
1272static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) 1237static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
1273{ 1238{
1274 struct cfg80211_registered_device *rdev; 1239 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1275 struct vif_params params; 1240 struct vif_params params;
1276 int err; 1241 int err;
1277 enum nl80211_iftype otype, ntype; 1242 enum nl80211_iftype otype, ntype;
1278 struct net_device *dev; 1243 struct net_device *dev = info->user_ptr[1];
1279 u32 _flags, *flags = NULL; 1244 u32 _flags, *flags = NULL;
1280 bool change = false; 1245 bool change = false;
1281 1246
1282 memset(&params, 0, sizeof(params)); 1247 memset(&params, 0, sizeof(params));
1283 1248
1284 rtnl_lock();
1285
1286 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
1287 if (err)
1288 goto unlock_rtnl;
1289
1290 otype = ntype = dev->ieee80211_ptr->iftype; 1249 otype = ntype = dev->ieee80211_ptr->iftype;
1291 1250
1292 if (info->attrs[NL80211_ATTR_IFTYPE]) { 1251 if (info->attrs[NL80211_ATTR_IFTYPE]) {
1293 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); 1252 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
1294 if (otype != ntype) 1253 if (otype != ntype)
1295 change = true; 1254 change = true;
1296 if (ntype > NL80211_IFTYPE_MAX) { 1255 if (ntype > NL80211_IFTYPE_MAX)
1297 err = -EINVAL; 1256 return -EINVAL;
1298 goto unlock;
1299 }
1300 } 1257 }
1301 1258
1302 if (info->attrs[NL80211_ATTR_MESH_ID]) { 1259 if (info->attrs[NL80211_ATTR_MESH_ID]) {
1303 if (ntype != NL80211_IFTYPE_MESH_POINT) { 1260 if (ntype != NL80211_IFTYPE_MESH_POINT)
1304 err = -EINVAL; 1261 return -EINVAL;
1305 goto unlock;
1306 }
1307 params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); 1262 params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
1308 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); 1263 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
1309 change = true; 1264 change = true;
@@ -1314,20 +1269,18 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
1314 change = true; 1269 change = true;
1315 err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype); 1270 err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
1316 if (err) 1271 if (err)
1317 goto unlock; 1272 return err;
1318 } else { 1273 } else {
1319 params.use_4addr = -1; 1274 params.use_4addr = -1;
1320 } 1275 }
1321 1276
1322 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { 1277 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
1323 if (ntype != NL80211_IFTYPE_MONITOR) { 1278 if (ntype != NL80211_IFTYPE_MONITOR)
1324 err = -EINVAL; 1279 return -EINVAL;
1325 goto unlock;
1326 }
1327 err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS], 1280 err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
1328 &_flags); 1281 &_flags);
1329 if (err) 1282 if (err)
1330 goto unlock; 1283 return err;
1331 1284
1332 flags = &_flags; 1285 flags = &_flags;
1333 change = true; 1286 change = true;
@@ -1341,17 +1294,12 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
1341 if (!err && params.use_4addr != -1) 1294 if (!err && params.use_4addr != -1)
1342 dev->ieee80211_ptr->use_4addr = params.use_4addr; 1295 dev->ieee80211_ptr->use_4addr = params.use_4addr;
1343 1296
1344 unlock:
1345 dev_put(dev);
1346 cfg80211_unlock_rdev(rdev);
1347 unlock_rtnl:
1348 rtnl_unlock();
1349 return err; 1297 return err;
1350} 1298}
1351 1299
1352static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) 1300static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
1353{ 1301{
1354 struct cfg80211_registered_device *rdev; 1302 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1355 struct vif_params params; 1303 struct vif_params params;
1356 int err; 1304 int err;
1357 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; 1305 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
@@ -1368,19 +1316,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
1368 return -EINVAL; 1316 return -EINVAL;
1369 } 1317 }
1370 1318
1371 rtnl_lock();
1372
1373 rdev = cfg80211_get_dev_from_info(info);
1374 if (IS_ERR(rdev)) {
1375 err = PTR_ERR(rdev);
1376 goto unlock_rtnl;
1377 }
1378
1379 if (!rdev->ops->add_virtual_intf || 1319 if (!rdev->ops->add_virtual_intf ||
1380 !(rdev->wiphy.interface_modes & (1 << type))) { 1320 !(rdev->wiphy.interface_modes & (1 << type)))
1381 err = -EOPNOTSUPP; 1321 return -EOPNOTSUPP;
1382 goto unlock;
1383 }
1384 1322
1385 if (type == NL80211_IFTYPE_MESH_POINT && 1323 if (type == NL80211_IFTYPE_MESH_POINT &&
1386 info->attrs[NL80211_ATTR_MESH_ID]) { 1324 info->attrs[NL80211_ATTR_MESH_ID]) {
@@ -1392,7 +1330,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
1392 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]); 1330 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
1393 err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type); 1331 err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
1394 if (err) 1332 if (err)
1395 goto unlock; 1333 return err;
1396 } 1334 }
1397 1335
1398 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? 1336 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)
1402 nla_data(info->attrs[NL80211_ATTR_IFNAME]), 1340 nla_data(info->attrs[NL80211_ATTR_IFNAME]),
1403 type, err ? NULL : &flags, &params); 1341 type, err ? NULL : &flags, &params);
1404 1342
1405 unlock:
1406 cfg80211_unlock_rdev(rdev);
1407 unlock_rtnl:
1408 rtnl_unlock();
1409 return err; 1343 return err;
1410} 1344}
1411 1345
1412static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) 1346static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
1413{ 1347{
1414 struct cfg80211_registered_device *rdev; 1348 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1415 int err; 1349 struct net_device *dev = info->user_ptr[1];
1416 struct net_device *dev;
1417
1418 rtnl_lock();
1419
1420 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
1421 if (err)
1422 goto unlock_rtnl;
1423 1350
1424 if (!rdev->ops->del_virtual_intf) { 1351 if (!rdev->ops->del_virtual_intf)
1425 err = -EOPNOTSUPP; 1352 return -EOPNOTSUPP;
1426 goto out;
1427 }
1428
1429 err = rdev->ops->del_virtual_intf(&rdev->wiphy, dev);
1430 1353
1431 out: 1354 return rdev->ops->del_virtual_intf(&rdev->wiphy, dev);
1432 cfg80211_unlock_rdev(rdev);
1433 dev_put(dev);
1434 unlock_rtnl:
1435 rtnl_unlock();
1436 return err;
1437} 1355}
1438 1356
1439struct get_key_cookie { 1357struct get_key_cookie {
@@ -1486,9 +1404,9 @@ static void get_key_callback(void *c, struct key_params *params)
1486 1404
1487static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) 1405static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
1488{ 1406{
1489 struct cfg80211_registered_device *rdev; 1407 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1490 int err; 1408 int err;
1491 struct net_device *dev; 1409 struct net_device *dev = info->user_ptr[1];
1492 u8 key_idx = 0; 1410 u8 key_idx = 0;
1493 u8 *mac_addr = NULL; 1411 u8 *mac_addr = NULL;
1494 struct get_key_cookie cookie = { 1412 struct get_key_cookie cookie = {
@@ -1506,30 +1424,17 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
1506 if (info->attrs[NL80211_ATTR_MAC]) 1424 if (info->attrs[NL80211_ATTR_MAC])
1507 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1425 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1508 1426
1509 rtnl_lock(); 1427 if (!rdev->ops->get_key)
1510 1428 return -EOPNOTSUPP;
1511 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
1512 if (err)
1513 goto unlock_rtnl;
1514
1515 if (!rdev->ops->get_key) {
1516 err = -EOPNOTSUPP;
1517 goto out;
1518 }
1519 1429
1520 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1430 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1521 if (!msg) { 1431 if (!msg)
1522 err = -ENOMEM; 1432 return -ENOMEM;
1523 goto out;
1524 }
1525 1433
1526 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, 1434 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
1527 NL80211_CMD_NEW_KEY); 1435 NL80211_CMD_NEW_KEY);
1528 1436 if (IS_ERR(hdr))
1529 if (IS_ERR(hdr)) { 1437 return PTR_ERR(hdr);
1530 err = PTR_ERR(hdr);
1531 goto free_msg;
1532 }
1533 1438
1534 cookie.msg = msg; 1439 cookie.msg = msg;
1535 cookie.idx = key_idx; 1440 cookie.idx = key_idx;
@@ -1549,28 +1454,21 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
1549 goto nla_put_failure; 1454 goto nla_put_failure;
1550 1455
1551 genlmsg_end(msg, hdr); 1456 genlmsg_end(msg, hdr);
1552 err = genlmsg_reply(msg, info); 1457 return genlmsg_reply(msg, info);
1553 goto out;
1554 1458
1555 nla_put_failure: 1459 nla_put_failure:
1556 err = -ENOBUFS; 1460 err = -ENOBUFS;
1557 free_msg: 1461 free_msg:
1558 nlmsg_free(msg); 1462 nlmsg_free(msg);
1559 out:
1560 cfg80211_unlock_rdev(rdev);
1561 dev_put(dev);
1562 unlock_rtnl:
1563 rtnl_unlock();
1564
1565 return err; 1463 return err;
1566} 1464}
1567 1465
1568static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) 1466static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
1569{ 1467{
1570 struct cfg80211_registered_device *rdev; 1468 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1571 struct key_parse key; 1469 struct key_parse key;
1572 int err; 1470 int err;
1573 struct net_device *dev; 1471 struct net_device *dev = info->user_ptr[1];
1574 int (*func)(struct wiphy *wiphy, struct net_device *netdev, 1472 int (*func)(struct wiphy *wiphy, struct net_device *netdev,
1575 u8 key_index); 1473 u8 key_index);
1576 1474
@@ -1585,21 +1483,13 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
1585 if (!key.def && !key.defmgmt) 1483 if (!key.def && !key.defmgmt)
1586 return -EINVAL; 1484 return -EINVAL;
1587 1485
1588 rtnl_lock();
1589
1590 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
1591 if (err)
1592 goto unlock_rtnl;
1593
1594 if (key.def) 1486 if (key.def)
1595 func = rdev->ops->set_default_key; 1487 func = rdev->ops->set_default_key;
1596 else 1488 else
1597 func = rdev->ops->set_default_mgmt_key; 1489 func = rdev->ops->set_default_mgmt_key;
1598 1490
1599 if (!func) { 1491 if (!func)
1600 err = -EOPNOTSUPP; 1492 return -EOPNOTSUPP;
1601 goto out;
1602 }
1603 1493
1604 wdev_lock(dev->ieee80211_ptr); 1494 wdev_lock(dev->ieee80211_ptr);
1605 err = nl80211_key_allowed(dev->ieee80211_ptr); 1495 err = nl80211_key_allowed(dev->ieee80211_ptr);
@@ -1616,21 +1506,14 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
1616#endif 1506#endif
1617 wdev_unlock(dev->ieee80211_ptr); 1507 wdev_unlock(dev->ieee80211_ptr);
1618 1508
1619 out:
1620 cfg80211_unlock_rdev(rdev);
1621 dev_put(dev);
1622
1623 unlock_rtnl:
1624 rtnl_unlock();
1625
1626 return err; 1509 return err;
1627} 1510}
1628 1511
1629static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) 1512static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1630{ 1513{
1631 struct cfg80211_registered_device *rdev; 1514 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1632 int err; 1515 int err;
1633 struct net_device *dev; 1516 struct net_device *dev = info->user_ptr[1];
1634 struct key_parse key; 1517 struct key_parse key;
1635 u8 *mac_addr = NULL; 1518 u8 *mac_addr = NULL;
1636 1519
@@ -1644,21 +1527,11 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1644 if (info->attrs[NL80211_ATTR_MAC]) 1527 if (info->attrs[NL80211_ATTR_MAC])
1645 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1528 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1646 1529
1647 rtnl_lock(); 1530 if (!rdev->ops->add_key)
1648 1531 return -EOPNOTSUPP;
1649 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
1650 if (err)
1651 goto unlock_rtnl;
1652
1653 if (!rdev->ops->add_key) {
1654 err = -EOPNOTSUPP;
1655 goto out;
1656 }
1657 1532
1658 if (cfg80211_validate_key_settings(rdev, &key.p, key.idx, mac_addr)) { 1533 if (cfg80211_validate_key_settings(rdev, &key.p, key.idx, mac_addr))
1659 err = -EINVAL; 1534 return -EINVAL;
1660 goto out;
1661 }
1662 1535
1663 wdev_lock(dev->ieee80211_ptr); 1536 wdev_lock(dev->ieee80211_ptr);
1664 err = nl80211_key_allowed(dev->ieee80211_ptr); 1537 err = nl80211_key_allowed(dev->ieee80211_ptr);
@@ -1667,20 +1540,14 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1667 mac_addr, &key.p); 1540 mac_addr, &key.p);
1668 wdev_unlock(dev->ieee80211_ptr); 1541 wdev_unlock(dev->ieee80211_ptr);
1669 1542
1670 out:
1671 cfg80211_unlock_rdev(rdev);
1672 dev_put(dev);
1673 unlock_rtnl:
1674 rtnl_unlock();
1675
1676 return err; 1543 return err;
1677} 1544}
1678 1545
1679static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) 1546static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
1680{ 1547{
1681 struct cfg80211_registered_device *rdev; 1548 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1682 int err; 1549 int err;
1683 struct net_device *dev; 1550 struct net_device *dev = info->user_ptr[1];
1684 u8 *mac_addr = NULL; 1551 u8 *mac_addr = NULL;
1685 struct key_parse key; 1552 struct key_parse key;
1686 1553
@@ -1691,16 +1558,8 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
1691 if (info->attrs[NL80211_ATTR_MAC]) 1558 if (info->attrs[NL80211_ATTR_MAC])
1692 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1559 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1693 1560
1694 rtnl_lock(); 1561 if (!rdev->ops->del_key)
1695 1562 return -EOPNOTSUPP;
1696 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
1697 if (err)
1698 goto unlock_rtnl;
1699
1700 if (!rdev->ops->del_key) {
1701 err = -EOPNOTSUPP;
1702 goto out;
1703 }
1704 1563
1705 wdev_lock(dev->ieee80211_ptr); 1564 wdev_lock(dev->ieee80211_ptr);
1706 err = nl80211_key_allowed(dev->ieee80211_ptr); 1565 err = nl80211_key_allowed(dev->ieee80211_ptr);
@@ -1717,13 +1576,6 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
1717#endif 1576#endif
1718 wdev_unlock(dev->ieee80211_ptr); 1577 wdev_unlock(dev->ieee80211_ptr);
1719 1578
1720 out:
1721 cfg80211_unlock_rdev(rdev);
1722 dev_put(dev);
1723
1724 unlock_rtnl:
1725 rtnl_unlock();
1726
1727 return err; 1579 return err;
1728} 1580}
1729 1581
@@ -1731,36 +1583,25 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
1731{ 1583{
1732 int (*call)(struct wiphy *wiphy, struct net_device *dev, 1584 int (*call)(struct wiphy *wiphy, struct net_device *dev,
1733 struct beacon_parameters *info); 1585 struct beacon_parameters *info);
1734 struct cfg80211_registered_device *rdev; 1586 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1735 int err; 1587 struct net_device *dev = info->user_ptr[1];
1736 struct net_device *dev;
1737 struct beacon_parameters params; 1588 struct beacon_parameters params;
1738 int haveinfo = 0; 1589 int haveinfo = 0;
1739 1590
1740 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL])) 1591 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL]))
1741 return -EINVAL; 1592 return -EINVAL;
1742 1593
1743 rtnl_lock();
1744
1745 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
1746 if (err)
1747 goto unlock_rtnl;
1748
1749 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 1594 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
1750 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { 1595 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
1751 err = -EOPNOTSUPP; 1596 return -EOPNOTSUPP;
1752 goto out;
1753 }
1754 1597
1755 switch (info->genlhdr->cmd) { 1598 switch (info->genlhdr->cmd) {
1756 case NL80211_CMD_NEW_BEACON: 1599 case NL80211_CMD_NEW_BEACON:
1757 /* these are required for NEW_BEACON */ 1600 /* these are required for NEW_BEACON */
1758 if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] || 1601 if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
1759 !info->attrs[NL80211_ATTR_DTIM_PERIOD] || 1602 !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
1760 !info->attrs[NL80211_ATTR_BEACON_HEAD]) { 1603 !info->attrs[NL80211_ATTR_BEACON_HEAD])
1761 err = -EINVAL; 1604 return -EINVAL;
1762 goto out;
1763 }
1764 1605
1765 call = rdev->ops->add_beacon; 1606 call = rdev->ops->add_beacon;
1766 break; 1607 break;
@@ -1769,14 +1610,11 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
1769 break; 1610 break;
1770 default: 1611 default:
1771 WARN_ON(1); 1612 WARN_ON(1);
1772 err = -EOPNOTSUPP; 1613 return -EOPNOTSUPP;
1773 goto out;
1774 } 1614 }
1775 1615
1776 if (!call) { 1616 if (!call)
1777 err = -EOPNOTSUPP; 1617 return -EOPNOTSUPP;
1778 goto out;
1779 }
1780 1618
1781 memset(&params, 0, sizeof(params)); 1619 memset(&params, 0, sizeof(params));
1782 1620
@@ -1806,53 +1644,25 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
1806 haveinfo = 1; 1644 haveinfo = 1;
1807 } 1645 }
1808 1646
1809 if (!haveinfo) { 1647 if (!haveinfo)
1810 err = -EINVAL; 1648 return -EINVAL;
1811 goto out;
1812 }
1813
1814 err = call(&rdev->wiphy, dev, &params);
1815
1816 out:
1817 cfg80211_unlock_rdev(rdev);
1818 dev_put(dev);
1819 unlock_rtnl:
1820 rtnl_unlock();
1821 1649
1822 return err; 1650 return call(&rdev->wiphy, dev, &params);
1823} 1651}
1824 1652
1825static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) 1653static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
1826{ 1654{
1827 struct cfg80211_registered_device *rdev; 1655 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1828 int err; 1656 struct net_device *dev = info->user_ptr[1];
1829 struct net_device *dev;
1830 1657
1831 rtnl_lock(); 1658 if (!rdev->ops->del_beacon)
1832 1659 return -EOPNOTSUPP;
1833 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
1834 if (err)
1835 goto unlock_rtnl;
1836
1837 if (!rdev->ops->del_beacon) {
1838 err = -EOPNOTSUPP;
1839 goto out;
1840 }
1841 1660
1842 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 1661 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
1843 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { 1662 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
1844 err = -EOPNOTSUPP; 1663 return -EOPNOTSUPP;
1845 goto out;
1846 }
1847 err = rdev->ops->del_beacon(&rdev->wiphy, dev);
1848
1849 out:
1850 cfg80211_unlock_rdev(rdev);
1851 dev_put(dev);
1852 unlock_rtnl:
1853 rtnl_unlock();
1854 1664
1855 return err; 1665 return rdev->ops->del_beacon(&rdev->wiphy, dev);
1856} 1666}
1857 1667
1858static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { 1668static 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,
2049 1859
2050static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) 1860static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
2051{ 1861{
2052 struct cfg80211_registered_device *rdev; 1862 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2053 int err; 1863 struct net_device *dev = info->user_ptr[1];
2054 struct net_device *dev;
2055 struct station_info sinfo; 1864 struct station_info sinfo;
2056 struct sk_buff *msg; 1865 struct sk_buff *msg;
2057 u8 *mac_addr = NULL; 1866 u8 *mac_addr = NULL;
1867 int err;
2058 1868
2059 memset(&sinfo, 0, sizeof(sinfo)); 1869 memset(&sinfo, 0, sizeof(sinfo));
2060 1870
@@ -2063,41 +1873,24 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
2063 1873
2064 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1874 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
2065 1875
2066 rtnl_lock(); 1876 if (!rdev->ops->get_station)
2067 1877 return -EOPNOTSUPP;
2068 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2069 if (err)
2070 goto out_rtnl;
2071
2072 if (!rdev->ops->get_station) {
2073 err = -EOPNOTSUPP;
2074 goto out;
2075 }
2076 1878
2077 err = rdev->ops->get_station(&rdev->wiphy, dev, mac_addr, &sinfo); 1879 err = rdev->ops->get_station(&rdev->wiphy, dev, mac_addr, &sinfo);
2078 if (err) 1880 if (err)
2079 goto out; 1881 return err;
2080 1882
2081 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1883 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2082 if (!msg) 1884 if (!msg)
2083 goto out; 1885 return -ENOMEM;
2084 1886
2085 if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0, 1887 if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
2086 dev, mac_addr, &sinfo) < 0) 1888 dev, mac_addr, &sinfo) < 0) {
2087 goto out_free; 1889 nlmsg_free(msg);
2088 1890 return -ENOBUFS;
2089 err = genlmsg_reply(msg, info); 1891 }
2090 goto out;
2091
2092 out_free:
2093 nlmsg_free(msg);
2094 out:
2095 cfg80211_unlock_rdev(rdev);
2096 dev_put(dev);
2097 out_rtnl:
2098 rtnl_unlock();
2099 1892
2100 return err; 1893 return genlmsg_reply(msg, info);
2101} 1894}
2102 1895
2103/* 1896/*
@@ -2127,9 +1920,9 @@ static int get_vlan(struct genl_info *info,
2127 1920
2128static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) 1921static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
2129{ 1922{
2130 struct cfg80211_registered_device *rdev; 1923 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2131 int err; 1924 int err;
2132 struct net_device *dev; 1925 struct net_device *dev = info->user_ptr[1];
2133 struct station_parameters params; 1926 struct station_parameters params;
2134 u8 *mac_addr = NULL; 1927 u8 *mac_addr = NULL;
2135 1928
@@ -2167,12 +1960,6 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
2167 params.plink_action = 1960 params.plink_action =
2168 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); 1961 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
2169 1962
2170 rtnl_lock();
2171
2172 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2173 if (err)
2174 goto out_rtnl;
2175
2176 err = get_vlan(info, rdev, &params.vlan); 1963 err = get_vlan(info, rdev, &params.vlan);
2177 if (err) 1964 if (err)
2178 goto out; 1965 goto out;
@@ -2234,19 +2021,15 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
2234 out: 2021 out:
2235 if (params.vlan) 2022 if (params.vlan)
2236 dev_put(params.vlan); 2023 dev_put(params.vlan);
2237 cfg80211_unlock_rdev(rdev);
2238 dev_put(dev);
2239 out_rtnl:
2240 rtnl_unlock();
2241 2024
2242 return err; 2025 return err;
2243} 2026}
2244 2027
2245static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) 2028static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
2246{ 2029{
2247 struct cfg80211_registered_device *rdev; 2030 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2248 int err; 2031 int err;
2249 struct net_device *dev; 2032 struct net_device *dev = info->user_ptr[1];
2250 struct station_parameters params; 2033 struct station_parameters params;
2251 u8 *mac_addr = NULL; 2034 u8 *mac_addr = NULL;
2252 2035
@@ -2283,18 +2066,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
2283 if (parse_station_flags(info, &params)) 2066 if (parse_station_flags(info, &params))
2284 return -EINVAL; 2067 return -EINVAL;
2285 2068
2286 rtnl_lock();
2287
2288 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2289 if (err)
2290 goto out_rtnl;
2291
2292 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 2069 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
2293 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && 2070 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
2294 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { 2071 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
2295 err = -EINVAL; 2072 return -EINVAL;
2296 goto out;
2297 }
2298 2073
2299 err = get_vlan(info, rdev, &params.vlan); 2074 err = get_vlan(info, rdev, &params.vlan);
2300 if (err) 2075 if (err)
@@ -2318,52 +2093,28 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
2318 out: 2093 out:
2319 if (params.vlan) 2094 if (params.vlan)
2320 dev_put(params.vlan); 2095 dev_put(params.vlan);
2321 cfg80211_unlock_rdev(rdev);
2322 dev_put(dev);
2323 out_rtnl:
2324 rtnl_unlock();
2325
2326 return err; 2096 return err;
2327} 2097}
2328 2098
2329static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) 2099static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
2330{ 2100{
2331 struct cfg80211_registered_device *rdev; 2101 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2332 int err; 2102 struct net_device *dev = info->user_ptr[1];
2333 struct net_device *dev;
2334 u8 *mac_addr = NULL; 2103 u8 *mac_addr = NULL;
2335 2104
2336 if (info->attrs[NL80211_ATTR_MAC]) 2105 if (info->attrs[NL80211_ATTR_MAC])
2337 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 2106 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
2338 2107
2339 rtnl_lock();
2340
2341 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2342 if (err)
2343 goto out_rtnl;
2344
2345 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 2108 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
2346 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && 2109 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
2347 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && 2110 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
2348 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { 2111 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
2349 err = -EINVAL; 2112 return -EINVAL;
2350 goto out;
2351 }
2352
2353 if (!rdev->ops->del_station) {
2354 err = -EOPNOTSUPP;
2355 goto out;
2356 }
2357
2358 err = rdev->ops->del_station(&rdev->wiphy, dev, mac_addr);
2359 2113
2360 out: 2114 if (!rdev->ops->del_station)
2361 cfg80211_unlock_rdev(rdev); 2115 return -EOPNOTSUPP;
2362 dev_put(dev);
2363 out_rtnl:
2364 rtnl_unlock();
2365 2116
2366 return err; 2117 return rdev->ops->del_station(&rdev->wiphy, dev, mac_addr);
2367} 2118}
2368 2119
2369static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq, 2120static 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,
2490 2241
2491static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) 2242static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
2492{ 2243{
2493 struct cfg80211_registered_device *rdev; 2244 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2494 int err; 2245 int err;
2495 struct net_device *dev; 2246 struct net_device *dev = info->user_ptr[1];
2496 struct mpath_info pinfo; 2247 struct mpath_info pinfo;
2497 struct sk_buff *msg; 2248 struct sk_buff *msg;
2498 u8 *dst = NULL; 2249 u8 *dst = NULL;
@@ -2505,53 +2256,33 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
2505 2256
2506 dst = nla_data(info->attrs[NL80211_ATTR_MAC]); 2257 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
2507 2258
2508 rtnl_lock(); 2259 if (!rdev->ops->get_mpath)
2509 2260 return -EOPNOTSUPP;
2510 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2511 if (err)
2512 goto out_rtnl;
2513
2514 if (!rdev->ops->get_mpath) {
2515 err = -EOPNOTSUPP;
2516 goto out;
2517 }
2518 2261
2519 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { 2262 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
2520 err = -EOPNOTSUPP; 2263 return -EOPNOTSUPP;
2521 goto out;
2522 }
2523 2264
2524 err = rdev->ops->get_mpath(&rdev->wiphy, dev, dst, next_hop, &pinfo); 2265 err = rdev->ops->get_mpath(&rdev->wiphy, dev, dst, next_hop, &pinfo);
2525 if (err) 2266 if (err)
2526 goto out; 2267 return err;
2527 2268
2528 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 2269 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2529 if (!msg) 2270 if (!msg)
2530 goto out; 2271 return -ENOMEM;
2531 2272
2532 if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0, 2273 if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0,
2533 dev, dst, next_hop, &pinfo) < 0) 2274 dev, dst, next_hop, &pinfo) < 0) {
2534 goto out_free; 2275 nlmsg_free(msg);
2535 2276 return -ENOBUFS;
2536 err = genlmsg_reply(msg, info); 2277 }
2537 goto out;
2538
2539 out_free:
2540 nlmsg_free(msg);
2541 out:
2542 cfg80211_unlock_rdev(rdev);
2543 dev_put(dev);
2544 out_rtnl:
2545 rtnl_unlock();
2546 2278
2547 return err; 2279 return genlmsg_reply(msg, info);
2548} 2280}
2549 2281
2550static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info) 2282static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
2551{ 2283{
2552 struct cfg80211_registered_device *rdev; 2284 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2553 int err; 2285 struct net_device *dev = info->user_ptr[1];
2554 struct net_device *dev;
2555 u8 *dst = NULL; 2286 u8 *dst = NULL;
2556 u8 *next_hop = NULL; 2287 u8 *next_hop = NULL;
2557 2288
@@ -2564,42 +2295,22 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
2564 dst = nla_data(info->attrs[NL80211_ATTR_MAC]); 2295 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
2565 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); 2296 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
2566 2297
2567 rtnl_lock(); 2298 if (!rdev->ops->change_mpath)
2568 2299 return -EOPNOTSUPP;
2569 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2570 if (err)
2571 goto out_rtnl;
2572
2573 if (!rdev->ops->change_mpath) {
2574 err = -EOPNOTSUPP;
2575 goto out;
2576 }
2577
2578 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
2579 err = -EOPNOTSUPP;
2580 goto out;
2581 }
2582
2583 if (!netif_running(dev)) {
2584 err = -ENETDOWN;
2585 goto out;
2586 }
2587 2300
2588 err = rdev->ops->change_mpath(&rdev->wiphy, dev, dst, next_hop); 2301 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
2302 return -EOPNOTSUPP;
2589 2303
2590 out: 2304 if (!netif_running(dev))
2591 cfg80211_unlock_rdev(rdev); 2305 return -ENETDOWN;
2592 dev_put(dev);
2593 out_rtnl:
2594 rtnl_unlock();
2595 2306
2596 return err; 2307 return rdev->ops->change_mpath(&rdev->wiphy, dev, dst, next_hop);
2597} 2308}
2309
2598static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) 2310static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
2599{ 2311{
2600 struct cfg80211_registered_device *rdev; 2312 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2601 int err; 2313 struct net_device *dev = info->user_ptr[1];
2602 struct net_device *dev;
2603 u8 *dst = NULL; 2314 u8 *dst = NULL;
2604 u8 *next_hop = NULL; 2315 u8 *next_hop = NULL;
2605 2316
@@ -2612,75 +2323,37 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
2612 dst = nla_data(info->attrs[NL80211_ATTR_MAC]); 2323 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
2613 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); 2324 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
2614 2325
2615 rtnl_lock(); 2326 if (!rdev->ops->add_mpath)
2616 2327 return -EOPNOTSUPP;
2617 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2618 if (err)
2619 goto out_rtnl;
2620
2621 if (!rdev->ops->add_mpath) {
2622 err = -EOPNOTSUPP;
2623 goto out;
2624 }
2625
2626 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
2627 err = -EOPNOTSUPP;
2628 goto out;
2629 }
2630
2631 if (!netif_running(dev)) {
2632 err = -ENETDOWN;
2633 goto out;
2634 }
2635 2328
2636 err = rdev->ops->add_mpath(&rdev->wiphy, dev, dst, next_hop); 2329 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
2330 return -EOPNOTSUPP;
2637 2331
2638 out: 2332 if (!netif_running(dev))
2639 cfg80211_unlock_rdev(rdev); 2333 return -ENETDOWN;
2640 dev_put(dev);
2641 out_rtnl:
2642 rtnl_unlock();
2643 2334
2644 return err; 2335 return rdev->ops->add_mpath(&rdev->wiphy, dev, dst, next_hop);
2645} 2336}
2646 2337
2647static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info) 2338static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
2648{ 2339{
2649 struct cfg80211_registered_device *rdev; 2340 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2650 int err; 2341 struct net_device *dev = info->user_ptr[1];
2651 struct net_device *dev;
2652 u8 *dst = NULL; 2342 u8 *dst = NULL;
2653 2343
2654 if (info->attrs[NL80211_ATTR_MAC]) 2344 if (info->attrs[NL80211_ATTR_MAC])
2655 dst = nla_data(info->attrs[NL80211_ATTR_MAC]); 2345 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
2656 2346
2657 rtnl_lock(); 2347 if (!rdev->ops->del_mpath)
2658 2348 return -EOPNOTSUPP;
2659 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2660 if (err)
2661 goto out_rtnl;
2662
2663 if (!rdev->ops->del_mpath) {
2664 err = -EOPNOTSUPP;
2665 goto out;
2666 }
2667
2668 err = rdev->ops->del_mpath(&rdev->wiphy, dev, dst);
2669
2670 out:
2671 cfg80211_unlock_rdev(rdev);
2672 dev_put(dev);
2673 out_rtnl:
2674 rtnl_unlock();
2675 2349
2676 return err; 2350 return rdev->ops->del_mpath(&rdev->wiphy, dev, dst);
2677} 2351}
2678 2352
2679static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) 2353static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
2680{ 2354{
2681 struct cfg80211_registered_device *rdev; 2355 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2682 int err; 2356 struct net_device *dev = info->user_ptr[1];
2683 struct net_device *dev;
2684 struct bss_parameters params; 2357 struct bss_parameters params;
2685 2358
2686 memset(&params, 0, sizeof(params)); 2359 memset(&params, 0, sizeof(params));
@@ -2708,32 +2381,14 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
2708 if (info->attrs[NL80211_ATTR_AP_ISOLATE]) 2381 if (info->attrs[NL80211_ATTR_AP_ISOLATE])
2709 params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]); 2382 params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]);
2710 2383
2711 rtnl_lock(); 2384 if (!rdev->ops->change_bss)
2712 2385 return -EOPNOTSUPP;
2713 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2714 if (err)
2715 goto out_rtnl;
2716
2717 if (!rdev->ops->change_bss) {
2718 err = -EOPNOTSUPP;
2719 goto out;
2720 }
2721 2386
2722 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 2387 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
2723 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { 2388 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
2724 err = -EOPNOTSUPP; 2389 return -EOPNOTSUPP;
2725 goto out;
2726 }
2727
2728 err = rdev->ops->change_bss(&rdev->wiphy, dev, &params);
2729
2730 out:
2731 cfg80211_unlock_rdev(rdev);
2732 dev_put(dev);
2733 out_rtnl:
2734 rtnl_unlock();
2735 2390
2736 return err; 2391 return rdev->ops->change_bss(&rdev->wiphy, dev, &params);
2737} 2392}
2738 2393
2739static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = { 2394static 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)
2812static int nl80211_get_mesh_params(struct sk_buff *skb, 2467static int nl80211_get_mesh_params(struct sk_buff *skb,
2813 struct genl_info *info) 2468 struct genl_info *info)
2814{ 2469{
2815 struct cfg80211_registered_device *rdev; 2470 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2816 struct mesh_config cur_params; 2471 struct mesh_config cur_params;
2817 int err; 2472 int err;
2818 struct net_device *dev; 2473 struct net_device *dev = info->user_ptr[1];
2819 void *hdr; 2474 void *hdr;
2820 struct nlattr *pinfoattr; 2475 struct nlattr *pinfoattr;
2821 struct sk_buff *msg; 2476 struct sk_buff *msg;
2822 2477
2823 rtnl_lock(); 2478 if (!rdev->ops->get_mesh_params)
2824 2479 return -EOPNOTSUPP;
2825 /* Look up our device */
2826 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2827 if (err)
2828 goto out_rtnl;
2829
2830 if (!rdev->ops->get_mesh_params) {
2831 err = -EOPNOTSUPP;
2832 goto out;
2833 }
2834 2480
2835 /* Get the mesh params */ 2481 /* Get the mesh params */
2836 err = rdev->ops->get_mesh_params(&rdev->wiphy, dev, &cur_params); 2482 err = rdev->ops->get_mesh_params(&rdev->wiphy, dev, &cur_params);
2837 if (err) 2483 if (err)
2838 goto out; 2484 return err;
2839 2485
2840 /* Draw up a netlink message to send back */ 2486 /* Draw up a netlink message to send back */
2841 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 2487 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2842 if (!msg) { 2488 if (!msg)
2843 err = -ENOBUFS; 2489 return -ENOMEM;
2844 goto out;
2845 }
2846 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, 2490 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
2847 NL80211_CMD_GET_MESH_PARAMS); 2491 NL80211_CMD_GET_MESH_PARAMS);
2848 if (!hdr) 2492 if (!hdr)
@@ -2881,21 +2525,12 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
2881 cur_params.dot11MeshHWMPRootMode); 2525 cur_params.dot11MeshHWMPRootMode);
2882 nla_nest_end(msg, pinfoattr); 2526 nla_nest_end(msg, pinfoattr);
2883 genlmsg_end(msg, hdr); 2527 genlmsg_end(msg, hdr);
2884 err = genlmsg_reply(msg, info); 2528 return genlmsg_reply(msg, info);
2885 goto out;
2886 2529
2887 nla_put_failure: 2530 nla_put_failure:
2888 genlmsg_cancel(msg, hdr); 2531 genlmsg_cancel(msg, hdr);
2889 nlmsg_free(msg); 2532 nlmsg_free(msg);
2890 err = -EMSGSIZE; 2533 return -ENOBUFS;
2891 out:
2892 /* Cleanup */
2893 cfg80211_unlock_rdev(rdev);
2894 dev_put(dev);
2895 out_rtnl:
2896 rtnl_unlock();
2897
2898 return err;
2899} 2534}
2900 2535
2901#define FILL_IN_MESH_PARAM_IF_SET(table, cfg, param, mask, attr_num, nla_fn) \ 2536#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
2925 2560
2926static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) 2561static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
2927{ 2562{
2928 int err;
2929 u32 mask; 2563 u32 mask;
2930 struct cfg80211_registered_device *rdev; 2564 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2931 struct net_device *dev; 2565 struct net_device *dev = info->user_ptr[1];
2932 struct mesh_config cfg; 2566 struct mesh_config cfg;
2933 struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1]; 2567 struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
2934 struct nlattr *parent_attr; 2568 struct nlattr *parent_attr;
@@ -2940,16 +2574,8 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
2940 parent_attr, nl80211_meshconf_params_policy)) 2574 parent_attr, nl80211_meshconf_params_policy))
2941 return -EINVAL; 2575 return -EINVAL;
2942 2576
2943 rtnl_lock(); 2577 if (!rdev->ops->set_mesh_params)
2944 2578 return -EOPNOTSUPP;
2945 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2946 if (err)
2947 goto out_rtnl;
2948
2949 if (!rdev->ops->set_mesh_params) {
2950 err = -EOPNOTSUPP;
2951 goto out;
2952 }
2953 2579
2954 /* This makes sure that there aren't more than 32 mesh config 2580 /* This makes sure that there aren't more than 32 mesh config
2955 * parameters (otherwise our bitfield scheme would not work.) */ 2581 * parameters (otherwise our bitfield scheme would not work.) */
@@ -2995,16 +2621,7 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
2995 nla_get_u8); 2621 nla_get_u8);
2996 2622
2997 /* Apply changes */ 2623 /* Apply changes */
2998 err = rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask); 2624 return rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask);
2999
3000 out:
3001 /* cleanup */
3002 cfg80211_unlock_rdev(rdev);
3003 dev_put(dev);
3004 out_rtnl:
3005 rtnl_unlock();
3006
3007 return err;
3008} 2625}
3009 2626
3010#undef FILL_IN_MESH_PARAM_IF_SET 2627#undef FILL_IN_MESH_PARAM_IF_SET
@@ -3187,8 +2804,8 @@ static int validate_scan_freqs(struct nlattr *freqs)
3187 2804
3188static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) 2805static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3189{ 2806{
3190 struct cfg80211_registered_device *rdev; 2807 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3191 struct net_device *dev; 2808 struct net_device *dev = info->user_ptr[1];
3192 struct cfg80211_scan_request *request; 2809 struct cfg80211_scan_request *request;
3193 struct cfg80211_ssid *ssid; 2810 struct cfg80211_ssid *ssid;
3194 struct ieee80211_channel *channel; 2811 struct ieee80211_channel *channel;
@@ -3201,36 +2818,22 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3201 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 2818 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3202 return -EINVAL; 2819 return -EINVAL;
3203 2820
3204 rtnl_lock();
3205
3206 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
3207 if (err)
3208 goto out_rtnl;
3209
3210 wiphy = &rdev->wiphy; 2821 wiphy = &rdev->wiphy;
3211 2822
3212 if (!rdev->ops->scan) { 2823 if (!rdev->ops->scan)
3213 err = -EOPNOTSUPP; 2824 return -EOPNOTSUPP;
3214 goto out;
3215 }
3216 2825
3217 if (!netif_running(dev)) { 2826 if (!netif_running(dev))
3218 err = -ENETDOWN; 2827 return -ENETDOWN;
3219 goto out;
3220 }
3221 2828
3222 if (rdev->scan_req) { 2829 if (rdev->scan_req)
3223 err = -EBUSY; 2830 return -EBUSY;
3224 goto out;
3225 }
3226 2831
3227 if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { 2832 if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
3228 n_channels = validate_scan_freqs( 2833 n_channels = validate_scan_freqs(
3229 info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]); 2834 info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
3230 if (!n_channels) { 2835 if (!n_channels)
3231 err = -EINVAL; 2836 return -EINVAL;
3232 goto out;
3233 }
3234 } else { 2837 } else {
3235 n_channels = 0; 2838 n_channels = 0;
3236 2839
@@ -3243,29 +2846,23 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3243 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) 2846 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
3244 n_ssids++; 2847 n_ssids++;
3245 2848
3246 if (n_ssids > wiphy->max_scan_ssids) { 2849 if (n_ssids > wiphy->max_scan_ssids)
3247 err = -EINVAL; 2850 return -EINVAL;
3248 goto out;
3249 }
3250 2851
3251 if (info->attrs[NL80211_ATTR_IE]) 2852 if (info->attrs[NL80211_ATTR_IE])
3252 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); 2853 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
3253 else 2854 else
3254 ie_len = 0; 2855 ie_len = 0;
3255 2856
3256 if (ie_len > wiphy->max_scan_ie_len) { 2857 if (ie_len > wiphy->max_scan_ie_len)
3257 err = -EINVAL; 2858 return -EINVAL;
3258 goto out;
3259 }
3260 2859
3261 request = kzalloc(sizeof(*request) 2860 request = kzalloc(sizeof(*request)
3262 + sizeof(*ssid) * n_ssids 2861 + sizeof(*ssid) * n_ssids
3263 + sizeof(channel) * n_channels 2862 + sizeof(channel) * n_channels
3264 + ie_len, GFP_KERNEL); 2863 + ie_len, GFP_KERNEL);
3265 if (!request) { 2864 if (!request)
3266 err = -ENOMEM; 2865 return -ENOMEM;
3267 goto out;
3268 }
3269 2866
3270 if (n_ssids) 2867 if (n_ssids)
3271 request->ssids = (void *)&request->channels[n_channels]; 2868 request->ssids = (void *)&request->channels[n_channels];
@@ -3353,18 +2950,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3353 if (!err) { 2950 if (!err) {
3354 nl80211_send_scan_start(rdev, dev); 2951 nl80211_send_scan_start(rdev, dev);
3355 dev_hold(dev); 2952 dev_hold(dev);
3356 } 2953 } else {
3357
3358 out_free: 2954 out_free:
3359 if (err) {
3360 rdev->scan_req = NULL; 2955 rdev->scan_req = NULL;
3361 kfree(request); 2956 kfree(request);
3362 } 2957 }
3363 out:
3364 cfg80211_unlock_rdev(rdev);
3365 dev_put(dev);
3366 out_rtnl:
3367 rtnl_unlock();
3368 2958
3369 return err; 2959 return err;
3370} 2960}
@@ -3643,8 +3233,8 @@ static bool nl80211_valid_cipher_suite(u32 cipher)
3643 3233
3644static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) 3234static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3645{ 3235{
3646 struct cfg80211_registered_device *rdev; 3236 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3647 struct net_device *dev; 3237 struct net_device *dev = info->user_ptr[1];
3648 struct ieee80211_channel *chan; 3238 struct ieee80211_channel *chan;
3649 const u8 *bssid, *ssid, *ie = NULL; 3239 const u8 *bssid, *ssid, *ie = NULL;
3650 int err, ssid_len, ie_len = 0; 3240 int err, ssid_len, ie_len = 0;
@@ -3686,12 +3276,6 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3686 key.p.key = NULL; 3276 key.p.key = NULL;
3687 } 3277 }
3688 3278
3689 rtnl_lock();
3690
3691 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
3692 if (err)
3693 goto unlock_rtnl;
3694
3695 if (key.idx >= 0) { 3279 if (key.idx >= 0) {
3696 int i; 3280 int i;
3697 bool ok = false; 3281 bool ok = false;
@@ -3701,35 +3285,25 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3701 break; 3285 break;
3702 } 3286 }
3703 } 3287 }
3704 if (!ok) { 3288 if (!ok)
3705 err = -EINVAL; 3289 return -EINVAL;
3706 goto out;
3707 }
3708 } 3290 }
3709 3291
3710 if (!rdev->ops->auth) { 3292 if (!rdev->ops->auth)
3711 err = -EOPNOTSUPP; 3293 return -EOPNOTSUPP;
3712 goto out;
3713 }
3714 3294
3715 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 3295 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
3716 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { 3296 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
3717 err = -EOPNOTSUPP; 3297 return -EOPNOTSUPP;
3718 goto out;
3719 }
3720 3298
3721 if (!netif_running(dev)) { 3299 if (!netif_running(dev))
3722 err = -ENETDOWN; 3300 return -ENETDOWN;
3723 goto out;
3724 }
3725 3301
3726 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); 3302 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
3727 chan = ieee80211_get_channel(&rdev->wiphy, 3303 chan = ieee80211_get_channel(&rdev->wiphy,
3728 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); 3304 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
3729 if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) { 3305 if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED))
3730 err = -EINVAL; 3306 return -EINVAL;
3731 goto out;
3732 }
3733 3307
3734 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); 3308 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
3735 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); 3309 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
@@ -3740,24 +3314,15 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3740 } 3314 }
3741 3315
3742 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); 3316 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
3743 if (!nl80211_valid_auth_type(auth_type)) { 3317 if (!nl80211_valid_auth_type(auth_type))
3744 err = -EINVAL; 3318 return -EINVAL;
3745 goto out;
3746 }
3747 3319
3748 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; 3320 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
3749 3321
3750 err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, 3322 return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
3751 ssid, ssid_len, ie, ie_len, 3323 ssid, ssid_len, ie, ie_len,
3752 key.p.key, key.p.key_len, key.idx, 3324 key.p.key, key.p.key_len, key.idx,
3753 local_state_change); 3325 local_state_change);
3754
3755out:
3756 cfg80211_unlock_rdev(rdev);
3757 dev_put(dev);
3758unlock_rtnl:
3759 rtnl_unlock();
3760 return err;
3761} 3326}
3762 3327
3763static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, 3328static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
@@ -3841,8 +3406,8 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
3841 3406
3842static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) 3407static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
3843{ 3408{
3844 struct cfg80211_registered_device *rdev; 3409 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3845 struct net_device *dev; 3410 struct net_device *dev = info->user_ptr[1];
3846 struct cfg80211_crypto_settings crypto; 3411 struct cfg80211_crypto_settings crypto;
3847 struct ieee80211_channel *chan; 3412 struct ieee80211_channel *chan;
3848 const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL; 3413 const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
@@ -3857,36 +3422,22 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
3857 !info->attrs[NL80211_ATTR_WIPHY_FREQ]) 3422 !info->attrs[NL80211_ATTR_WIPHY_FREQ])
3858 return -EINVAL; 3423 return -EINVAL;
3859 3424
3860 rtnl_lock(); 3425 if (!rdev->ops->assoc)
3861 3426 return -EOPNOTSUPP;
3862 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
3863 if (err)
3864 goto unlock_rtnl;
3865
3866 if (!rdev->ops->assoc) {
3867 err = -EOPNOTSUPP;
3868 goto out;
3869 }
3870 3427
3871 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 3428 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
3872 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { 3429 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
3873 err = -EOPNOTSUPP; 3430 return -EOPNOTSUPP;
3874 goto out;
3875 }
3876 3431
3877 if (!netif_running(dev)) { 3432 if (!netif_running(dev))
3878 err = -ENETDOWN; 3433 return -ENETDOWN;
3879 goto out;
3880 }
3881 3434
3882 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); 3435 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
3883 3436
3884 chan = ieee80211_get_channel(&rdev->wiphy, 3437 chan = ieee80211_get_channel(&rdev->wiphy,
3885 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); 3438 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
3886 if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) { 3439 if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED))
3887 err = -EINVAL; 3440 return -EINVAL;
3888 goto out;
3889 }
3890 3441
3891 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); 3442 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
3892 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); 3443 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
@@ -3901,10 +3452,8 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
3901 nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]); 3452 nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
3902 if (mfp == NL80211_MFP_REQUIRED) 3453 if (mfp == NL80211_MFP_REQUIRED)
3903 use_mfp = true; 3454 use_mfp = true;
3904 else if (mfp != NL80211_MFP_NO) { 3455 else if (mfp != NL80211_MFP_NO)
3905 err = -EINVAL; 3456 return -EINVAL;
3906 goto out;
3907 }
3908 } 3457 }
3909 3458
3910 if (info->attrs[NL80211_ATTR_PREV_BSSID]) 3459 if (info->attrs[NL80211_ATTR_PREV_BSSID])
@@ -3916,20 +3465,15 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
3916 ssid, ssid_len, ie, ie_len, use_mfp, 3465 ssid, ssid_len, ie, ie_len, use_mfp,
3917 &crypto); 3466 &crypto);
3918 3467
3919out:
3920 cfg80211_unlock_rdev(rdev);
3921 dev_put(dev);
3922unlock_rtnl:
3923 rtnl_unlock();
3924 return err; 3468 return err;
3925} 3469}
3926 3470
3927static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) 3471static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
3928{ 3472{
3929 struct cfg80211_registered_device *rdev; 3473 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3930 struct net_device *dev; 3474 struct net_device *dev = info->user_ptr[1];
3931 const u8 *ie = NULL, *bssid; 3475 const u8 *ie = NULL, *bssid;
3932 int err, ie_len = 0; 3476 int ie_len = 0;
3933 u16 reason_code; 3477 u16 reason_code;
3934 bool local_state_change; 3478 bool local_state_change;
3935 3479
@@ -3942,35 +3486,22 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
3942 if (!info->attrs[NL80211_ATTR_REASON_CODE]) 3486 if (!info->attrs[NL80211_ATTR_REASON_CODE])
3943 return -EINVAL; 3487 return -EINVAL;
3944 3488
3945 rtnl_lock(); 3489 if (!rdev->ops->deauth)
3946 3490 return -EOPNOTSUPP;
3947 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
3948 if (err)
3949 goto unlock_rtnl;
3950
3951 if (!rdev->ops->deauth) {
3952 err = -EOPNOTSUPP;
3953 goto out;
3954 }
3955 3491
3956 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 3492 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
3957 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { 3493 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
3958 err = -EOPNOTSUPP; 3494 return -EOPNOTSUPP;
3959 goto out;
3960 }
3961 3495
3962 if (!netif_running(dev)) { 3496 if (!netif_running(dev))
3963 err = -ENETDOWN; 3497 return -ENETDOWN;
3964 goto out;
3965 }
3966 3498
3967 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); 3499 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
3968 3500
3969 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); 3501 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
3970 if (reason_code == 0) { 3502 if (reason_code == 0) {
3971 /* Reason Code 0 is reserved */ 3503 /* Reason Code 0 is reserved */
3972 err = -EINVAL; 3504 return -EINVAL;
3973 goto out;
3974 } 3505 }
3975 3506
3976 if (info->attrs[NL80211_ATTR_IE]) { 3507 if (info->attrs[NL80211_ATTR_IE]) {
@@ -3980,23 +3511,16 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
3980 3511
3981 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; 3512 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
3982 3513
3983 err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code, 3514 return cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
3984 local_state_change); 3515 local_state_change);
3985
3986out:
3987 cfg80211_unlock_rdev(rdev);
3988 dev_put(dev);
3989unlock_rtnl:
3990 rtnl_unlock();
3991 return err;
3992} 3516}
3993 3517
3994static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) 3518static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
3995{ 3519{
3996 struct cfg80211_registered_device *rdev; 3520 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3997 struct net_device *dev; 3521 struct net_device *dev = info->user_ptr[1];
3998 const u8 *ie = NULL, *bssid; 3522 const u8 *ie = NULL, *bssid;
3999 int err, ie_len = 0; 3523 int ie_len = 0;
4000 u16 reason_code; 3524 u16 reason_code;
4001 bool local_state_change; 3525 bool local_state_change;
4002 3526
@@ -4009,35 +3533,22 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
4009 if (!info->attrs[NL80211_ATTR_REASON_CODE]) 3533 if (!info->attrs[NL80211_ATTR_REASON_CODE])
4010 return -EINVAL; 3534 return -EINVAL;
4011 3535
4012 rtnl_lock(); 3536 if (!rdev->ops->disassoc)
4013 3537 return -EOPNOTSUPP;
4014 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4015 if (err)
4016 goto unlock_rtnl;
4017
4018 if (!rdev->ops->disassoc) {
4019 err = -EOPNOTSUPP;
4020 goto out;
4021 }
4022 3538
4023 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 3539 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4024 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { 3540 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
4025 err = -EOPNOTSUPP; 3541 return -EOPNOTSUPP;
4026 goto out;
4027 }
4028 3542
4029 if (!netif_running(dev)) { 3543 if (!netif_running(dev))
4030 err = -ENETDOWN; 3544 return -ENETDOWN;
4031 goto out;
4032 }
4033 3545
4034 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); 3546 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
4035 3547
4036 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); 3548 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
4037 if (reason_code == 0) { 3549 if (reason_code == 0) {
4038 /* Reason Code 0 is reserved */ 3550 /* Reason Code 0 is reserved */
4039 err = -EINVAL; 3551 return -EINVAL;
4040 goto out;
4041 } 3552 }
4042 3553
4043 if (info->attrs[NL80211_ATTR_IE]) { 3554 if (info->attrs[NL80211_ATTR_IE]) {
@@ -4047,21 +3558,14 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
4047 3558
4048 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; 3559 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
4049 3560
4050 err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code, 3561 return cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
4051 local_state_change); 3562 local_state_change);
4052
4053out:
4054 cfg80211_unlock_rdev(rdev);
4055 dev_put(dev);
4056unlock_rtnl:
4057 rtnl_unlock();
4058 return err;
4059} 3563}
4060 3564
4061static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) 3565static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
4062{ 3566{
4063 struct cfg80211_registered_device *rdev; 3567 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4064 struct net_device *dev; 3568 struct net_device *dev = info->user_ptr[1];
4065 struct cfg80211_ibss_params ibss; 3569 struct cfg80211_ibss_params ibss;
4066 struct wiphy *wiphy; 3570 struct wiphy *wiphy;
4067 struct cfg80211_cached_keys *connkeys = NULL; 3571 struct cfg80211_cached_keys *connkeys = NULL;
@@ -4086,26 +3590,14 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
4086 return -EINVAL; 3590 return -EINVAL;
4087 } 3591 }
4088 3592
4089 rtnl_lock(); 3593 if (!rdev->ops->join_ibss)
4090 3594 return -EOPNOTSUPP;
4091 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4092 if (err)
4093 goto unlock_rtnl;
4094
4095 if (!rdev->ops->join_ibss) {
4096 err = -EOPNOTSUPP;
4097 goto out;
4098 }
4099 3595
4100 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) { 3596 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
4101 err = -EOPNOTSUPP; 3597 return -EOPNOTSUPP;
4102 goto out;
4103 }
4104 3598
4105 if (!netif_running(dev)) { 3599 if (!netif_running(dev))
4106 err = -ENETDOWN; 3600 return -ENETDOWN;
4107 goto out;
4108 }
4109 3601
4110 wiphy = &rdev->wiphy; 3602 wiphy = &rdev->wiphy;
4111 3603
@@ -4123,24 +3615,12 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
4123 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); 3615 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
4124 if (!ibss.channel || 3616 if (!ibss.channel ||
4125 ibss.channel->flags & IEEE80211_CHAN_NO_IBSS || 3617 ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
4126 ibss.channel->flags & IEEE80211_CHAN_DISABLED) { 3618 ibss.channel->flags & IEEE80211_CHAN_DISABLED)
4127 err = -EINVAL; 3619 return -EINVAL;
4128 goto out;
4129 }
4130 3620
4131 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; 3621 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
4132 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; 3622 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
4133 3623
4134 if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
4135 connkeys = nl80211_parse_connkeys(rdev,
4136 info->attrs[NL80211_ATTR_KEYS]);
4137 if (IS_ERR(connkeys)) {
4138 err = PTR_ERR(connkeys);
4139 connkeys = NULL;
4140 goto out;
4141 }
4142 }
4143
4144 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) { 3624 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
4145 u8 *rates = 3625 u8 *rates =
4146 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); 3626 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
@@ -4150,10 +3630,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
4150 wiphy->bands[ibss.channel->band]; 3630 wiphy->bands[ibss.channel->band];
4151 int i, j; 3631 int i, j;
4152 3632
4153 if (n_rates == 0) { 3633 if (n_rates == 0)
4154 err = -EINVAL; 3634 return -EINVAL;
4155 goto out;
4156 }
4157 3635
4158 for (i = 0; i < n_rates; i++) { 3636 for (i = 0; i < n_rates; i++) {
4159 int rate = (rates[i] & 0x7f) * 5; 3637 int rate = (rates[i] & 0x7f) * 5;
@@ -4166,60 +3644,39 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
4166 break; 3644 break;
4167 } 3645 }
4168 } 3646 }
4169 if (!found) { 3647 if (!found)
4170 err = -EINVAL; 3648 return -EINVAL;
4171 goto out;
4172 }
4173 } 3649 }
4174 } 3650 }
4175 3651
4176 err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); 3652 if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
3653 connkeys = nl80211_parse_connkeys(rdev,
3654 info->attrs[NL80211_ATTR_KEYS]);
3655 if (IS_ERR(connkeys))
3656 return PTR_ERR(connkeys);
3657 }
4177 3658
4178out: 3659 err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
4179 cfg80211_unlock_rdev(rdev);
4180 dev_put(dev);
4181unlock_rtnl:
4182 if (err) 3660 if (err)
4183 kfree(connkeys); 3661 kfree(connkeys);
4184 rtnl_unlock();
4185 return err; 3662 return err;
4186} 3663}
4187 3664
4188static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info) 3665static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
4189{ 3666{
4190 struct cfg80211_registered_device *rdev; 3667 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4191 struct net_device *dev; 3668 struct net_device *dev = info->user_ptr[1];
4192 int err;
4193
4194 rtnl_lock();
4195
4196 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4197 if (err)
4198 goto unlock_rtnl;
4199 3669
4200 if (!rdev->ops->leave_ibss) { 3670 if (!rdev->ops->leave_ibss)
4201 err = -EOPNOTSUPP; 3671 return -EOPNOTSUPP;
4202 goto out;
4203 }
4204
4205 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) {
4206 err = -EOPNOTSUPP;
4207 goto out;
4208 }
4209 3672
4210 if (!netif_running(dev)) { 3673 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
4211 err = -ENETDOWN; 3674 return -EOPNOTSUPP;
4212 goto out;
4213 }
4214 3675
4215 err = cfg80211_leave_ibss(rdev, dev, false); 3676 if (!netif_running(dev))
3677 return -ENETDOWN;
4216 3678
4217out: 3679 return cfg80211_leave_ibss(rdev, dev, false);
4218 cfg80211_unlock_rdev(rdev);
4219 dev_put(dev);
4220unlock_rtnl:
4221 rtnl_unlock();
4222 return err;
4223} 3680}
4224 3681
4225#ifdef CONFIG_NL80211_TESTMODE 3682#ifdef CONFIG_NL80211_TESTMODE
@@ -4229,20 +3686,12 @@ static struct genl_multicast_group nl80211_testmode_mcgrp = {
4229 3686
4230static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info) 3687static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
4231{ 3688{
4232 struct cfg80211_registered_device *rdev; 3689 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4233 int err; 3690 int err;
4234 3691
4235 if (!info->attrs[NL80211_ATTR_TESTDATA]) 3692 if (!info->attrs[NL80211_ATTR_TESTDATA])
4236 return -EINVAL; 3693 return -EINVAL;
4237 3694
4238 rtnl_lock();
4239
4240 rdev = cfg80211_get_dev_from_info(info);
4241 if (IS_ERR(rdev)) {
4242 err = PTR_ERR(rdev);
4243 goto unlock_rtnl;
4244 }
4245
4246 err = -EOPNOTSUPP; 3695 err = -EOPNOTSUPP;
4247 if (rdev->ops->testmode_cmd) { 3696 if (rdev->ops->testmode_cmd) {
4248 rdev->testmode_info = info; 3697 rdev->testmode_info = info;
@@ -4252,10 +3701,6 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
4252 rdev->testmode_info = NULL; 3701 rdev->testmode_info = NULL;
4253 } 3702 }
4254 3703
4255 cfg80211_unlock_rdev(rdev);
4256
4257 unlock_rtnl:
4258 rtnl_unlock();
4259 return err; 3704 return err;
4260} 3705}
4261 3706
@@ -4346,8 +3791,8 @@ EXPORT_SYMBOL(cfg80211_testmode_event);
4346 3791
4347static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) 3792static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
4348{ 3793{
4349 struct cfg80211_registered_device *rdev; 3794 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4350 struct net_device *dev; 3795 struct net_device *dev = info->user_ptr[1];
4351 struct cfg80211_connect_params connect; 3796 struct cfg80211_connect_params connect;
4352 struct wiphy *wiphy; 3797 struct wiphy *wiphy;
4353 struct cfg80211_cached_keys *connkeys = NULL; 3798 struct cfg80211_cached_keys *connkeys = NULL;
@@ -4376,22 +3821,13 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
4376 NL80211_MAX_NR_CIPHER_SUITES); 3821 NL80211_MAX_NR_CIPHER_SUITES);
4377 if (err) 3822 if (err)
4378 return err; 3823 return err;
4379 rtnl_lock();
4380
4381 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4382 if (err)
4383 goto unlock_rtnl;
4384 3824
4385 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 3825 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4386 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { 3826 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
4387 err = -EOPNOTSUPP; 3827 return -EOPNOTSUPP;
4388 goto out;
4389 }
4390 3828
4391 if (!netif_running(dev)) { 3829 if (!netif_running(dev))
4392 err = -ENETDOWN; 3830 return -ENETDOWN;
4393 goto out;
4394 }
4395 3831
4396 wiphy = &rdev->wiphy; 3832 wiphy = &rdev->wiphy;
4397 3833
@@ -4410,39 +3846,27 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
4410 ieee80211_get_channel(wiphy, 3846 ieee80211_get_channel(wiphy,
4411 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); 3847 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
4412 if (!connect.channel || 3848 if (!connect.channel ||
4413 connect.channel->flags & IEEE80211_CHAN_DISABLED) { 3849 connect.channel->flags & IEEE80211_CHAN_DISABLED)
4414 err = -EINVAL; 3850 return -EINVAL;
4415 goto out;
4416 }
4417 } 3851 }
4418 3852
4419 if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) { 3853 if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
4420 connkeys = nl80211_parse_connkeys(rdev, 3854 connkeys = nl80211_parse_connkeys(rdev,
4421 info->attrs[NL80211_ATTR_KEYS]); 3855 info->attrs[NL80211_ATTR_KEYS]);
4422 if (IS_ERR(connkeys)) { 3856 if (IS_ERR(connkeys))
4423 err = PTR_ERR(connkeys); 3857 return PTR_ERR(connkeys);
4424 connkeys = NULL;
4425 goto out;
4426 }
4427 } 3858 }
4428 3859
4429 err = cfg80211_connect(rdev, dev, &connect, connkeys); 3860 err = cfg80211_connect(rdev, dev, &connect, connkeys);
4430
4431out:
4432 cfg80211_unlock_rdev(rdev);
4433 dev_put(dev);
4434unlock_rtnl:
4435 if (err) 3861 if (err)
4436 kfree(connkeys); 3862 kfree(connkeys);
4437 rtnl_unlock();
4438 return err; 3863 return err;
4439} 3864}
4440 3865
4441static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info) 3866static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
4442{ 3867{
4443 struct cfg80211_registered_device *rdev; 3868 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4444 struct net_device *dev; 3869 struct net_device *dev = info->user_ptr[1];
4445 int err;
4446 u16 reason; 3870 u16 reason;
4447 3871
4448 if (!info->attrs[NL80211_ATTR_REASON_CODE]) 3872 if (!info->attrs[NL80211_ATTR_REASON_CODE])
@@ -4453,36 +3877,19 @@ static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
4453 if (reason == 0) 3877 if (reason == 0)
4454 return -EINVAL; 3878 return -EINVAL;
4455 3879
4456 rtnl_lock();
4457
4458 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4459 if (err)
4460 goto unlock_rtnl;
4461
4462 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 3880 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4463 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { 3881 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
4464 err = -EOPNOTSUPP; 3882 return -EOPNOTSUPP;
4465 goto out;
4466 }
4467
4468 if (!netif_running(dev)) {
4469 err = -ENETDOWN;
4470 goto out;
4471 }
4472 3883
4473 err = cfg80211_disconnect(rdev, dev, reason, true); 3884 if (!netif_running(dev))
3885 return -ENETDOWN;
4474 3886
4475out: 3887 return cfg80211_disconnect(rdev, dev, reason, true);
4476 cfg80211_unlock_rdev(rdev);
4477 dev_put(dev);
4478unlock_rtnl:
4479 rtnl_unlock();
4480 return err;
4481} 3888}
4482 3889
4483static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info) 3890static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
4484{ 3891{
4485 struct cfg80211_registered_device *rdev; 3892 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4486 struct net *net; 3893 struct net *net;
4487 int err; 3894 int err;
4488 u32 pid; 3895 u32 pid;
@@ -4492,43 +3899,26 @@ static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
4492 3899
4493 pid = nla_get_u32(info->attrs[NL80211_ATTR_PID]); 3900 pid = nla_get_u32(info->attrs[NL80211_ATTR_PID]);
4494 3901
4495 rtnl_lock();
4496
4497 rdev = cfg80211_get_dev_from_info(info);
4498 if (IS_ERR(rdev)) {
4499 err = PTR_ERR(rdev);
4500 goto out_rtnl;
4501 }
4502
4503 net = get_net_ns_by_pid(pid); 3902 net = get_net_ns_by_pid(pid);
4504 if (IS_ERR(net)) { 3903 if (IS_ERR(net))
4505 err = PTR_ERR(net); 3904 return PTR_ERR(net);
4506 goto out;
4507 }
4508 3905
4509 err = 0; 3906 err = 0;
4510 3907
4511 /* check if anything to do */ 3908 /* check if anything to do */
4512 if (net_eq(wiphy_net(&rdev->wiphy), net)) 3909 if (!net_eq(wiphy_net(&rdev->wiphy), net))
4513 goto out_put_net; 3910 err = cfg80211_switch_netns(rdev, net);
4514 3911
4515 err = cfg80211_switch_netns(rdev, net);
4516 out_put_net:
4517 put_net(net); 3912 put_net(net);
4518 out:
4519 cfg80211_unlock_rdev(rdev);
4520 out_rtnl:
4521 rtnl_unlock();
4522 return err; 3913 return err;
4523} 3914}
4524 3915
4525static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info) 3916static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
4526{ 3917{
4527 struct cfg80211_registered_device *rdev; 3918 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4528 int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev, 3919 int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev,
4529 struct cfg80211_pmksa *pmksa) = NULL; 3920 struct cfg80211_pmksa *pmksa) = NULL;
4530 int err; 3921 struct net_device *dev = info->user_ptr[1];
4531 struct net_device *dev;
4532 struct cfg80211_pmksa pmksa; 3922 struct cfg80211_pmksa pmksa;
4533 3923
4534 memset(&pmksa, 0, sizeof(struct cfg80211_pmksa)); 3924 memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
@@ -4539,20 +3929,12 @@ static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
4539 if (!info->attrs[NL80211_ATTR_PMKID]) 3929 if (!info->attrs[NL80211_ATTR_PMKID])
4540 return -EINVAL; 3930 return -EINVAL;
4541 3931
4542 rtnl_lock();
4543
4544 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4545 if (err)
4546 goto out_rtnl;
4547
4548 pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]); 3932 pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
4549 pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); 3933 pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
4550 3934
4551 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 3935 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4552 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { 3936 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
4553 err = -EOPNOTSUPP; 3937 return -EOPNOTSUPP;
4554 goto out;
4555 }
4556 3938
4557 switch (info->genlhdr->cmd) { 3939 switch (info->genlhdr->cmd) {
4558 case NL80211_CMD_SET_PMKSA: 3940 case NL80211_CMD_SET_PMKSA:
@@ -4566,62 +3948,32 @@ static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
4566 break; 3948 break;
4567 } 3949 }
4568 3950
4569 if (!rdev_ops) { 3951 if (!rdev_ops)
4570 err = -EOPNOTSUPP; 3952 return -EOPNOTSUPP;
4571 goto out;
4572 }
4573
4574 err = rdev_ops(&rdev->wiphy, dev, &pmksa);
4575
4576 out:
4577 cfg80211_unlock_rdev(rdev);
4578 dev_put(dev);
4579 out_rtnl:
4580 rtnl_unlock();
4581 3953
4582 return err; 3954 return rdev_ops(&rdev->wiphy, dev, &pmksa);
4583} 3955}
4584 3956
4585static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info) 3957static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
4586{ 3958{
4587 struct cfg80211_registered_device *rdev; 3959 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4588 int err; 3960 struct net_device *dev = info->user_ptr[1];
4589 struct net_device *dev;
4590
4591 rtnl_lock();
4592
4593 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4594 if (err)
4595 goto out_rtnl;
4596 3961
4597 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 3962 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4598 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { 3963 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
4599 err = -EOPNOTSUPP; 3964 return -EOPNOTSUPP;
4600 goto out;
4601 }
4602
4603 if (!rdev->ops->flush_pmksa) {
4604 err = -EOPNOTSUPP;
4605 goto out;
4606 }
4607
4608 err = rdev->ops->flush_pmksa(&rdev->wiphy, dev);
4609
4610 out:
4611 cfg80211_unlock_rdev(rdev);
4612 dev_put(dev);
4613 out_rtnl:
4614 rtnl_unlock();
4615 3965
4616 return err; 3966 if (!rdev->ops->flush_pmksa)
3967 return -EOPNOTSUPP;
4617 3968
3969 return rdev->ops->flush_pmksa(&rdev->wiphy, dev);
4618} 3970}
4619 3971
4620static int nl80211_remain_on_channel(struct sk_buff *skb, 3972static int nl80211_remain_on_channel(struct sk_buff *skb,
4621 struct genl_info *info) 3973 struct genl_info *info)
4622{ 3974{
4623 struct cfg80211_registered_device *rdev; 3975 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4624 struct net_device *dev; 3976 struct net_device *dev = info->user_ptr[1];
4625 struct ieee80211_channel *chan; 3977 struct ieee80211_channel *chan;
4626 struct sk_buff *msg; 3978 struct sk_buff *msg;
4627 void *hdr; 3979 void *hdr;
@@ -4643,21 +3995,11 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
4643 if (!duration || !msecs_to_jiffies(duration) || duration > 5000) 3995 if (!duration || !msecs_to_jiffies(duration) || duration > 5000)
4644 return -EINVAL; 3996 return -EINVAL;
4645 3997
4646 rtnl_lock(); 3998 if (!rdev->ops->remain_on_channel)
4647 3999 return -EOPNOTSUPP;
4648 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4649 if (err)
4650 goto unlock_rtnl;
4651
4652 if (!rdev->ops->remain_on_channel) {
4653 err = -EOPNOTSUPP;
4654 goto out;
4655 }
4656 4000
4657 if (!netif_running(dev)) { 4001 if (!netif_running(dev))
4658 err = -ENETDOWN; 4002 return -ENETDOWN;
4659 goto out;
4660 }
4661 4003
4662 if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { 4004 if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
4663 channel_type = nla_get_u32( 4005 channel_type = nla_get_u32(
@@ -4665,24 +4007,18 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
4665 if (channel_type != NL80211_CHAN_NO_HT && 4007 if (channel_type != NL80211_CHAN_NO_HT &&
4666 channel_type != NL80211_CHAN_HT20 && 4008 channel_type != NL80211_CHAN_HT20 &&
4667 channel_type != NL80211_CHAN_HT40PLUS && 4009 channel_type != NL80211_CHAN_HT40PLUS &&
4668 channel_type != NL80211_CHAN_HT40MINUS) { 4010 channel_type != NL80211_CHAN_HT40MINUS)
4669 err = -EINVAL; 4011 return -EINVAL;
4670 goto out;
4671 }
4672 } 4012 }
4673 4013
4674 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); 4014 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
4675 chan = rdev_freq_to_chan(rdev, freq, channel_type); 4015 chan = rdev_freq_to_chan(rdev, freq, channel_type);
4676 if (chan == NULL) { 4016 if (chan == NULL)
4677 err = -EINVAL; 4017 return -EINVAL;
4678 goto out;
4679 }
4680 4018
4681 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 4019 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4682 if (!msg) { 4020 if (!msg)
4683 err = -ENOMEM; 4021 return -ENOMEM;
4684 goto out;
4685 }
4686 4022
4687 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, 4023 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
4688 NL80211_CMD_REMAIN_ON_CHANNEL); 4024 NL80211_CMD_REMAIN_ON_CHANNEL);
@@ -4701,58 +4037,35 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
4701 NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); 4037 NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
4702 4038
4703 genlmsg_end(msg, hdr); 4039 genlmsg_end(msg, hdr);
4704 err = genlmsg_reply(msg, info); 4040
4705 goto out; 4041 return genlmsg_reply(msg, info);
4706 4042
4707 nla_put_failure: 4043 nla_put_failure:
4708 err = -ENOBUFS; 4044 err = -ENOBUFS;
4709 free_msg: 4045 free_msg:
4710 nlmsg_free(msg); 4046 nlmsg_free(msg);
4711 out:
4712 cfg80211_unlock_rdev(rdev);
4713 dev_put(dev);
4714 unlock_rtnl:
4715 rtnl_unlock();
4716 return err; 4047 return err;
4717} 4048}
4718 4049
4719static int nl80211_cancel_remain_on_channel(struct sk_buff *skb, 4050static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
4720 struct genl_info *info) 4051 struct genl_info *info)
4721{ 4052{
4722 struct cfg80211_registered_device *rdev; 4053 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4723 struct net_device *dev; 4054 struct net_device *dev = info->user_ptr[1];
4724 u64 cookie; 4055 u64 cookie;
4725 int err;
4726 4056
4727 if (!info->attrs[NL80211_ATTR_COOKIE]) 4057 if (!info->attrs[NL80211_ATTR_COOKIE])
4728 return -EINVAL; 4058 return -EINVAL;
4729 4059
4730 rtnl_lock(); 4060 if (!rdev->ops->cancel_remain_on_channel)
4731 4061 return -EOPNOTSUPP;
4732 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4733 if (err)
4734 goto unlock_rtnl;
4735
4736 if (!rdev->ops->cancel_remain_on_channel) {
4737 err = -EOPNOTSUPP;
4738 goto out;
4739 }
4740 4062
4741 if (!netif_running(dev)) { 4063 if (!netif_running(dev))
4742 err = -ENETDOWN; 4064 return -ENETDOWN;
4743 goto out;
4744 }
4745 4065
4746 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]); 4066 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
4747 4067
4748 err = rdev->ops->cancel_remain_on_channel(&rdev->wiphy, dev, cookie); 4068 return rdev->ops->cancel_remain_on_channel(&rdev->wiphy, dev, cookie);
4749
4750 out:
4751 cfg80211_unlock_rdev(rdev);
4752 dev_put(dev);
4753 unlock_rtnl:
4754 rtnl_unlock();
4755 return err;
4756} 4069}
4757 4070
4758static u32 rateset_to_mask(struct ieee80211_supported_band *sband, 4071static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
@@ -4788,26 +4101,18 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
4788 struct genl_info *info) 4101 struct genl_info *info)
4789{ 4102{
4790 struct nlattr *tb[NL80211_TXRATE_MAX + 1]; 4103 struct nlattr *tb[NL80211_TXRATE_MAX + 1];
4791 struct cfg80211_registered_device *rdev; 4104 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4792 struct cfg80211_bitrate_mask mask; 4105 struct cfg80211_bitrate_mask mask;
4793 int err, rem, i; 4106 int rem, i;
4794 struct net_device *dev; 4107 struct net_device *dev = info->user_ptr[1];
4795 struct nlattr *tx_rates; 4108 struct nlattr *tx_rates;
4796 struct ieee80211_supported_band *sband; 4109 struct ieee80211_supported_band *sband;
4797 4110
4798 if (info->attrs[NL80211_ATTR_TX_RATES] == NULL) 4111 if (info->attrs[NL80211_ATTR_TX_RATES] == NULL)
4799 return -EINVAL; 4112 return -EINVAL;
4800 4113
4801 rtnl_lock(); 4114 if (!rdev->ops->set_bitrate_mask)
4802 4115 return -EOPNOTSUPP;
4803 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4804 if (err)
4805 goto unlock_rtnl;
4806
4807 if (!rdev->ops->set_bitrate_mask) {
4808 err = -EOPNOTSUPP;
4809 goto unlock;
4810 }
4811 4116
4812 memset(&mask, 0, sizeof(mask)); 4117 memset(&mask, 0, sizeof(mask));
4813 /* Default to all rates enabled */ 4118 /* Default to all rates enabled */
@@ -4824,15 +4129,11 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
4824 nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) 4129 nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem)
4825 { 4130 {
4826 enum ieee80211_band band = nla_type(tx_rates); 4131 enum ieee80211_band band = nla_type(tx_rates);
4827 if (band < 0 || band >= IEEE80211_NUM_BANDS) { 4132 if (band < 0 || band >= IEEE80211_NUM_BANDS)
4828 err = -EINVAL; 4133 return -EINVAL;
4829 goto unlock;
4830 }
4831 sband = rdev->wiphy.bands[band]; 4134 sband = rdev->wiphy.bands[band];
4832 if (sband == NULL) { 4135 if (sband == NULL)
4833 err = -EINVAL; 4136 return -EINVAL;
4834 goto unlock;
4835 }
4836 nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates), 4137 nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
4837 nla_len(tx_rates), nl80211_txattr_policy); 4138 nla_len(tx_rates), nl80211_txattr_policy);
4838 if (tb[NL80211_TXRATE_LEGACY]) { 4139 if (tb[NL80211_TXRATE_LEGACY]) {
@@ -4840,29 +4141,19 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
4840 sband, 4141 sband,
4841 nla_data(tb[NL80211_TXRATE_LEGACY]), 4142 nla_data(tb[NL80211_TXRATE_LEGACY]),
4842 nla_len(tb[NL80211_TXRATE_LEGACY])); 4143 nla_len(tb[NL80211_TXRATE_LEGACY]));
4843 if (mask.control[band].legacy == 0) { 4144 if (mask.control[band].legacy == 0)
4844 err = -EINVAL; 4145 return -EINVAL;
4845 goto unlock;
4846 }
4847 } 4146 }
4848 } 4147 }
4849 4148
4850 err = rdev->ops->set_bitrate_mask(&rdev->wiphy, dev, NULL, &mask); 4149 return rdev->ops->set_bitrate_mask(&rdev->wiphy, dev, NULL, &mask);
4851
4852 unlock:
4853 dev_put(dev);
4854 cfg80211_unlock_rdev(rdev);
4855 unlock_rtnl:
4856 rtnl_unlock();
4857 return err;
4858} 4150}
4859 4151
4860static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) 4152static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
4861{ 4153{
4862 struct cfg80211_registered_device *rdev; 4154 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4863 struct net_device *dev; 4155 struct net_device *dev = info->user_ptr[1];
4864 u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION; 4156 u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION;
4865 int err;
4866 4157
4867 if (!info->attrs[NL80211_ATTR_FRAME_MATCH]) 4158 if (!info->attrs[NL80211_ATTR_FRAME_MATCH])
4868 return -EINVAL; 4159 return -EINVAL;
@@ -4870,44 +4161,28 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
4870 if (info->attrs[NL80211_ATTR_FRAME_TYPE]) 4161 if (info->attrs[NL80211_ATTR_FRAME_TYPE])
4871 frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]); 4162 frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]);
4872 4163
4873 rtnl_lock();
4874
4875 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4876 if (err)
4877 goto unlock_rtnl;
4878
4879 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 4164 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4880 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC && 4165 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
4881 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT && 4166 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
4882 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 4167 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4883 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && 4168 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
4884 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { 4169 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
4885 err = -EOPNOTSUPP; 4170 return -EOPNOTSUPP;
4886 goto out;
4887 }
4888 4171
4889 /* not much point in registering if we can't reply */ 4172 /* not much point in registering if we can't reply */
4890 if (!rdev->ops->mgmt_tx) { 4173 if (!rdev->ops->mgmt_tx)
4891 err = -EOPNOTSUPP; 4174 return -EOPNOTSUPP;
4892 goto out;
4893 }
4894 4175
4895 err = cfg80211_mlme_register_mgmt(dev->ieee80211_ptr, info->snd_pid, 4176 return cfg80211_mlme_register_mgmt(dev->ieee80211_ptr, info->snd_pid,
4896 frame_type, 4177 frame_type,
4897 nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), 4178 nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
4898 nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); 4179 nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]));
4899 out:
4900 cfg80211_unlock_rdev(rdev);
4901 dev_put(dev);
4902 unlock_rtnl:
4903 rtnl_unlock();
4904 return err;
4905} 4180}
4906 4181
4907static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) 4182static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
4908{ 4183{
4909 struct cfg80211_registered_device *rdev; 4184 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4910 struct net_device *dev; 4185 struct net_device *dev = info->user_ptr[1];
4911 struct ieee80211_channel *chan; 4186 struct ieee80211_channel *chan;
4912 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; 4187 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
4913 bool channel_type_valid = false; 4188 bool channel_type_valid = false;
@@ -4921,31 +4196,19 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
4921 !info->attrs[NL80211_ATTR_WIPHY_FREQ]) 4196 !info->attrs[NL80211_ATTR_WIPHY_FREQ])
4922 return -EINVAL; 4197 return -EINVAL;
4923 4198
4924 rtnl_lock(); 4199 if (!rdev->ops->mgmt_tx)
4925 4200 return -EOPNOTSUPP;
4926 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4927 if (err)
4928 goto unlock_rtnl;
4929
4930 if (!rdev->ops->mgmt_tx) {
4931 err = -EOPNOTSUPP;
4932 goto out;
4933 }
4934 4201
4935 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 4202 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4936 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC && 4203 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
4937 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT && 4204 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
4938 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 4205 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4939 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && 4206 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
4940 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { 4207 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
4941 err = -EOPNOTSUPP; 4208 return -EOPNOTSUPP;
4942 goto out;
4943 }
4944 4209
4945 if (!netif_running(dev)) { 4210 if (!netif_running(dev))
4946 err = -ENETDOWN; 4211 return -ENETDOWN;
4947 goto out;
4948 }
4949 4212
4950 if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { 4213 if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
4951 channel_type = nla_get_u32( 4214 channel_type = nla_get_u32(
@@ -4953,25 +4216,19 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
4953 if (channel_type != NL80211_CHAN_NO_HT && 4216 if (channel_type != NL80211_CHAN_NO_HT &&
4954 channel_type != NL80211_CHAN_HT20 && 4217 channel_type != NL80211_CHAN_HT20 &&
4955 channel_type != NL80211_CHAN_HT40PLUS && 4218 channel_type != NL80211_CHAN_HT40PLUS &&
4956 channel_type != NL80211_CHAN_HT40MINUS) { 4219 channel_type != NL80211_CHAN_HT40MINUS)
4957 err = -EINVAL; 4220 return -EINVAL;
4958 goto out;
4959 }
4960 channel_type_valid = true; 4221 channel_type_valid = true;
4961 } 4222 }
4962 4223
4963 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); 4224 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
4964 chan = rdev_freq_to_chan(rdev, freq, channel_type); 4225 chan = rdev_freq_to_chan(rdev, freq, channel_type);
4965 if (chan == NULL) { 4226 if (chan == NULL)
4966 err = -EINVAL; 4227 return -EINVAL;
4967 goto out;
4968 }
4969 4228
4970 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 4229 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4971 if (!msg) { 4230 if (!msg)
4972 err = -ENOMEM; 4231 return -ENOMEM;
4973 goto out;
4974 }
4975 4232
4976 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, 4233 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
4977 NL80211_CMD_FRAME); 4234 NL80211_CMD_FRAME);
@@ -4991,110 +4248,72 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
4991 NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); 4248 NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
4992 4249
4993 genlmsg_end(msg, hdr); 4250 genlmsg_end(msg, hdr);
4994 err = genlmsg_reply(msg, info); 4251 return genlmsg_reply(msg, info);
4995 goto out;
4996 4252
4997 nla_put_failure: 4253 nla_put_failure:
4998 err = -ENOBUFS; 4254 err = -ENOBUFS;
4999 free_msg: 4255 free_msg:
5000 nlmsg_free(msg); 4256 nlmsg_free(msg);
5001 out:
5002 cfg80211_unlock_rdev(rdev);
5003 dev_put(dev);
5004unlock_rtnl:
5005 rtnl_unlock();
5006 return err; 4257 return err;
5007} 4258}
5008 4259
5009static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info) 4260static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
5010{ 4261{
5011 struct cfg80211_registered_device *rdev; 4262 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5012 struct wireless_dev *wdev; 4263 struct wireless_dev *wdev;
5013 struct net_device *dev; 4264 struct net_device *dev = info->user_ptr[1];
5014 u8 ps_state; 4265 u8 ps_state;
5015 bool state; 4266 bool state;
5016 int err; 4267 int err;
5017 4268
5018 if (!info->attrs[NL80211_ATTR_PS_STATE]) { 4269 if (!info->attrs[NL80211_ATTR_PS_STATE])
5019 err = -EINVAL; 4270 return -EINVAL;
5020 goto out;
5021 }
5022 4271
5023 ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]); 4272 ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]);
5024 4273
5025 if (ps_state != NL80211_PS_DISABLED && ps_state != NL80211_PS_ENABLED) { 4274 if (ps_state != NL80211_PS_DISABLED && ps_state != NL80211_PS_ENABLED)
5026 err = -EINVAL; 4275 return -EINVAL;
5027 goto out;
5028 }
5029
5030 rtnl_lock();
5031
5032 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
5033 if (err)
5034 goto unlock_rtnl;
5035 4276
5036 wdev = dev->ieee80211_ptr; 4277 wdev = dev->ieee80211_ptr;
5037 4278
5038 if (!rdev->ops->set_power_mgmt) { 4279 if (!rdev->ops->set_power_mgmt)
5039 err = -EOPNOTSUPP; 4280 return -EOPNOTSUPP;
5040 goto unlock_rdev;
5041 }
5042 4281
5043 state = (ps_state == NL80211_PS_ENABLED) ? true : false; 4282 state = (ps_state == NL80211_PS_ENABLED) ? true : false;
5044 4283
5045 if (state == wdev->ps) 4284 if (state == wdev->ps)
5046 goto unlock_rdev; 4285 return 0;
5047
5048 wdev->ps = state;
5049
5050 if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, wdev->ps,
5051 wdev->ps_timeout))
5052 /* assume this means it's off */
5053 wdev->ps = false;
5054
5055unlock_rdev:
5056 cfg80211_unlock_rdev(rdev);
5057 dev_put(dev);
5058unlock_rtnl:
5059 rtnl_unlock();
5060 4286
5061out: 4287 err = rdev->ops->set_power_mgmt(wdev->wiphy, dev, state,
4288 wdev->ps_timeout);
4289 if (!err)
4290 wdev->ps = state;
5062 return err; 4291 return err;
5063} 4292}
5064 4293
5065static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info) 4294static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
5066{ 4295{
5067 struct cfg80211_registered_device *rdev; 4296 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5068 enum nl80211_ps_state ps_state; 4297 enum nl80211_ps_state ps_state;
5069 struct wireless_dev *wdev; 4298 struct wireless_dev *wdev;
5070 struct net_device *dev; 4299 struct net_device *dev = info->user_ptr[1];
5071 struct sk_buff *msg; 4300 struct sk_buff *msg;
5072 void *hdr; 4301 void *hdr;
5073 int err; 4302 int err;
5074 4303
5075 rtnl_lock();
5076
5077 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
5078 if (err)
5079 goto unlock_rtnl;
5080
5081 wdev = dev->ieee80211_ptr; 4304 wdev = dev->ieee80211_ptr;
5082 4305
5083 if (!rdev->ops->set_power_mgmt) { 4306 if (!rdev->ops->set_power_mgmt)
5084 err = -EOPNOTSUPP; 4307 return -EOPNOTSUPP;
5085 goto out;
5086 }
5087 4308
5088 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 4309 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5089 if (!msg) { 4310 if (!msg)
5090 err = -ENOMEM; 4311 return -ENOMEM;
5091 goto out;
5092 }
5093 4312
5094 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, 4313 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
5095 NL80211_CMD_GET_POWER_SAVE); 4314 NL80211_CMD_GET_POWER_SAVE);
5096 if (!hdr) { 4315 if (!hdr) {
5097 err = -ENOMEM; 4316 err = -ENOBUFS;
5098 goto free_msg; 4317 goto free_msg;
5099 } 4318 }
5100 4319
@@ -5106,22 +4325,12 @@ static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
5106 NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, ps_state); 4325 NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, ps_state);
5107 4326
5108 genlmsg_end(msg, hdr); 4327 genlmsg_end(msg, hdr);
5109 err = genlmsg_reply(msg, info); 4328 return genlmsg_reply(msg, info);
5110 goto out;
5111 4329
5112nla_put_failure: 4330 nla_put_failure:
5113 err = -ENOBUFS; 4331 err = -ENOBUFS;
5114 4332 free_msg:
5115free_msg:
5116 nlmsg_free(msg); 4333 nlmsg_free(msg);
5117
5118out:
5119 cfg80211_unlock_rdev(rdev);
5120 dev_put(dev);
5121
5122unlock_rtnl:
5123 rtnl_unlock();
5124
5125 return err; 4334 return err;
5126} 4335}
5127 4336
@@ -5135,43 +4344,24 @@ nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] __read_mostly = {
5135static int nl80211_set_cqm_rssi(struct genl_info *info, 4344static int nl80211_set_cqm_rssi(struct genl_info *info,
5136 s32 threshold, u32 hysteresis) 4345 s32 threshold, u32 hysteresis)
5137{ 4346{
5138 struct cfg80211_registered_device *rdev; 4347 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5139 struct wireless_dev *wdev; 4348 struct wireless_dev *wdev;
5140 struct net_device *dev; 4349 struct net_device *dev = info->user_ptr[1];
5141 int err;
5142 4350
5143 if (threshold > 0) 4351 if (threshold > 0)
5144 return -EINVAL; 4352 return -EINVAL;
5145 4353
5146 rtnl_lock();
5147
5148 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
5149 if (err)
5150 goto unlock_rtnl;
5151
5152 wdev = dev->ieee80211_ptr; 4354 wdev = dev->ieee80211_ptr;
5153 4355
5154 if (!rdev->ops->set_cqm_rssi_config) { 4356 if (!rdev->ops->set_cqm_rssi_config)
5155 err = -EOPNOTSUPP; 4357 return -EOPNOTSUPP;
5156 goto unlock_rdev;
5157 }
5158 4358
5159 if (wdev->iftype != NL80211_IFTYPE_STATION && 4359 if (wdev->iftype != NL80211_IFTYPE_STATION &&
5160 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) { 4360 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
5161 err = -EOPNOTSUPP; 4361 return -EOPNOTSUPP;
5162 goto unlock_rdev;
5163 }
5164
5165 err = rdev->ops->set_cqm_rssi_config(wdev->wiphy, dev,
5166 threshold, hysteresis);
5167
5168 unlock_rdev:
5169 cfg80211_unlock_rdev(rdev);
5170 dev_put(dev);
5171 unlock_rtnl:
5172 rtnl_unlock();
5173 4362
5174 return err; 4363 return rdev->ops->set_cqm_rssi_config(wdev->wiphy, dev,
4364 threshold, hysteresis);
5175} 4365}
5176 4366
5177static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info) 4367static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
@@ -5205,6 +4395,54 @@ out:
5205 return err; 4395 return err;
5206} 4396}
5207 4397
4398#define NL80211_FLAG_NEED_WIPHY 0x01
4399#define NL80211_FLAG_NEED_NETDEV 0x02
4400#define NL80211_FLAG_NEED_RTNL 0x04
4401
4402static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
4403 struct genl_info *info)
4404{
4405 struct cfg80211_registered_device *rdev;
4406 struct net_device *dev;
4407 int err;
4408 bool rtnl = ops->internal_flags & NL80211_FLAG_NEED_RTNL;
4409
4410 if (rtnl)
4411 rtnl_lock();
4412
4413 if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) {
4414 rdev = cfg80211_get_dev_from_info(info);
4415 if (IS_ERR(rdev)) {
4416 if (rtnl)
4417 rtnl_unlock();
4418 return PTR_ERR(rdev);
4419 }
4420 info->user_ptr[0] = rdev;
4421 } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
4422 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4423 if (err) {
4424 if (rtnl)
4425 rtnl_unlock();
4426 return err;
4427 }
4428 info->user_ptr[0] = rdev;
4429 info->user_ptr[1] = dev;
4430 }
4431
4432 return 0;
4433}
4434
4435static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
4436 struct genl_info *info)
4437{
4438 if (info->user_ptr[0])
4439 cfg80211_unlock_rdev(info->user_ptr[0]);
4440 if (info->user_ptr[1])
4441 dev_put(info->user_ptr[1]);
4442 if (ops->internal_flags & NL80211_FLAG_NEED_RTNL)
4443 rtnl_unlock();
4444}
4445
5208static struct genl_ops nl80211_ops[] = { 4446static struct genl_ops nl80211_ops[] = {
5209 { 4447 {
5210 .cmd = NL80211_CMD_GET_WIPHY, 4448 .cmd = NL80211_CMD_GET_WIPHY,
@@ -5212,12 +4450,14 @@ static struct genl_ops nl80211_ops[] = {
5212 .dumpit = nl80211_dump_wiphy, 4450 .dumpit = nl80211_dump_wiphy,
5213 .policy = nl80211_policy, 4451 .policy = nl80211_policy,
5214 /* can be retrieved by unprivileged users */ 4452 /* can be retrieved by unprivileged users */
4453 .internal_flags = NL80211_FLAG_NEED_WIPHY,
5215 }, 4454 },
5216 { 4455 {
5217 .cmd = NL80211_CMD_SET_WIPHY, 4456 .cmd = NL80211_CMD_SET_WIPHY,
5218 .doit = nl80211_set_wiphy, 4457 .doit = nl80211_set_wiphy,
5219 .policy = nl80211_policy, 4458 .policy = nl80211_policy,
5220 .flags = GENL_ADMIN_PERM, 4459 .flags = GENL_ADMIN_PERM,
4460 .internal_flags = NL80211_FLAG_NEED_RTNL,
5221 }, 4461 },
5222 { 4462 {
5223 .cmd = NL80211_CMD_GET_INTERFACE, 4463 .cmd = NL80211_CMD_GET_INTERFACE,
@@ -5225,90 +4465,119 @@ static struct genl_ops nl80211_ops[] = {
5225 .dumpit = nl80211_dump_interface, 4465 .dumpit = nl80211_dump_interface,
5226 .policy = nl80211_policy, 4466 .policy = nl80211_policy,
5227 /* can be retrieved by unprivileged users */ 4467 /* can be retrieved by unprivileged users */
4468 .internal_flags = NL80211_FLAG_NEED_NETDEV,
5228 }, 4469 },
5229 { 4470 {
5230 .cmd = NL80211_CMD_SET_INTERFACE, 4471 .cmd = NL80211_CMD_SET_INTERFACE,
5231 .doit = nl80211_set_interface, 4472 .doit = nl80211_set_interface,
5232 .policy = nl80211_policy, 4473 .policy = nl80211_policy,
5233 .flags = GENL_ADMIN_PERM, 4474 .flags = GENL_ADMIN_PERM,
4475 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4476 NL80211_FLAG_NEED_RTNL,
5234 }, 4477 },
5235 { 4478 {
5236 .cmd = NL80211_CMD_NEW_INTERFACE, 4479 .cmd = NL80211_CMD_NEW_INTERFACE,
5237 .doit = nl80211_new_interface, 4480 .doit = nl80211_new_interface,
5238 .policy = nl80211_policy, 4481 .policy = nl80211_policy,
5239 .flags = GENL_ADMIN_PERM, 4482 .flags = GENL_ADMIN_PERM,
4483 .internal_flags = NL80211_FLAG_NEED_WIPHY |
4484 NL80211_FLAG_NEED_RTNL,
5240 }, 4485 },
5241 { 4486 {
5242 .cmd = NL80211_CMD_DEL_INTERFACE, 4487 .cmd = NL80211_CMD_DEL_INTERFACE,
5243 .doit = nl80211_del_interface, 4488 .doit = nl80211_del_interface,
5244 .policy = nl80211_policy, 4489 .policy = nl80211_policy,
5245 .flags = GENL_ADMIN_PERM, 4490 .flags = GENL_ADMIN_PERM,
4491 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4492 NL80211_FLAG_NEED_RTNL,
5246 }, 4493 },
5247 { 4494 {
5248 .cmd = NL80211_CMD_GET_KEY, 4495 .cmd = NL80211_CMD_GET_KEY,
5249 .doit = nl80211_get_key, 4496 .doit = nl80211_get_key,
5250 .policy = nl80211_policy, 4497 .policy = nl80211_policy,
5251 .flags = GENL_ADMIN_PERM, 4498 .flags = GENL_ADMIN_PERM,
4499 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4500 NL80211_FLAG_NEED_RTNL,
5252 }, 4501 },
5253 { 4502 {
5254 .cmd = NL80211_CMD_SET_KEY, 4503 .cmd = NL80211_CMD_SET_KEY,
5255 .doit = nl80211_set_key, 4504 .doit = nl80211_set_key,
5256 .policy = nl80211_policy, 4505 .policy = nl80211_policy,
5257 .flags = GENL_ADMIN_PERM, 4506 .flags = GENL_ADMIN_PERM,
4507 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4508 NL80211_FLAG_NEED_RTNL,
5258 }, 4509 },
5259 { 4510 {
5260 .cmd = NL80211_CMD_NEW_KEY, 4511 .cmd = NL80211_CMD_NEW_KEY,
5261 .doit = nl80211_new_key, 4512 .doit = nl80211_new_key,
5262 .policy = nl80211_policy, 4513 .policy = nl80211_policy,
5263 .flags = GENL_ADMIN_PERM, 4514 .flags = GENL_ADMIN_PERM,
4515 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4516 NL80211_FLAG_NEED_RTNL,
5264 }, 4517 },
5265 { 4518 {
5266 .cmd = NL80211_CMD_DEL_KEY, 4519 .cmd = NL80211_CMD_DEL_KEY,
5267 .doit = nl80211_del_key, 4520 .doit = nl80211_del_key,
5268 .policy = nl80211_policy, 4521 .policy = nl80211_policy,
5269 .flags = GENL_ADMIN_PERM, 4522 .flags = GENL_ADMIN_PERM,
4523 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4524 NL80211_FLAG_NEED_RTNL,
5270 }, 4525 },
5271 { 4526 {
5272 .cmd = NL80211_CMD_SET_BEACON, 4527 .cmd = NL80211_CMD_SET_BEACON,
5273 .policy = nl80211_policy, 4528 .policy = nl80211_policy,
5274 .flags = GENL_ADMIN_PERM, 4529 .flags = GENL_ADMIN_PERM,
5275 .doit = nl80211_addset_beacon, 4530 .doit = nl80211_addset_beacon,
4531 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4532 NL80211_FLAG_NEED_RTNL,
5276 }, 4533 },
5277 { 4534 {
5278 .cmd = NL80211_CMD_NEW_BEACON, 4535 .cmd = NL80211_CMD_NEW_BEACON,
5279 .policy = nl80211_policy, 4536 .policy = nl80211_policy,
5280 .flags = GENL_ADMIN_PERM, 4537 .flags = GENL_ADMIN_PERM,
5281 .doit = nl80211_addset_beacon, 4538 .doit = nl80211_addset_beacon,
4539 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4540 NL80211_FLAG_NEED_RTNL,
5282 }, 4541 },
5283 { 4542 {
5284 .cmd = NL80211_CMD_DEL_BEACON, 4543 .cmd = NL80211_CMD_DEL_BEACON,
5285 .policy = nl80211_policy, 4544 .policy = nl80211_policy,
5286 .flags = GENL_ADMIN_PERM, 4545 .flags = GENL_ADMIN_PERM,
5287 .doit = nl80211_del_beacon, 4546 .doit = nl80211_del_beacon,
4547 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4548 NL80211_FLAG_NEED_RTNL,
5288 }, 4549 },
5289 { 4550 {
5290 .cmd = NL80211_CMD_GET_STATION, 4551 .cmd = NL80211_CMD_GET_STATION,
5291 .doit = nl80211_get_station, 4552 .doit = nl80211_get_station,
5292 .dumpit = nl80211_dump_station, 4553 .dumpit = nl80211_dump_station,
5293 .policy = nl80211_policy, 4554 .policy = nl80211_policy,
4555 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4556 NL80211_FLAG_NEED_RTNL,
5294 }, 4557 },
5295 { 4558 {
5296 .cmd = NL80211_CMD_SET_STATION, 4559 .cmd = NL80211_CMD_SET_STATION,
5297 .doit = nl80211_set_station, 4560 .doit = nl80211_set_station,
5298 .policy = nl80211_policy, 4561 .policy = nl80211_policy,
5299 .flags = GENL_ADMIN_PERM, 4562 .flags = GENL_ADMIN_PERM,
4563 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4564 NL80211_FLAG_NEED_RTNL,
5300 }, 4565 },
5301 { 4566 {
5302 .cmd = NL80211_CMD_NEW_STATION, 4567 .cmd = NL80211_CMD_NEW_STATION,
5303 .doit = nl80211_new_station, 4568 .doit = nl80211_new_station,
5304 .policy = nl80211_policy, 4569 .policy = nl80211_policy,
5305 .flags = GENL_ADMIN_PERM, 4570 .flags = GENL_ADMIN_PERM,
4571 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4572 NL80211_FLAG_NEED_RTNL,
5306 }, 4573 },
5307 { 4574 {
5308 .cmd = NL80211_CMD_DEL_STATION, 4575 .cmd = NL80211_CMD_DEL_STATION,
5309 .doit = nl80211_del_station, 4576 .doit = nl80211_del_station,
5310 .policy = nl80211_policy, 4577 .policy = nl80211_policy,
5311 .flags = GENL_ADMIN_PERM, 4578 .flags = GENL_ADMIN_PERM,
4579 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4580 NL80211_FLAG_NEED_RTNL,
5312 }, 4581 },
5313 { 4582 {
5314 .cmd = NL80211_CMD_GET_MPATH, 4583 .cmd = NL80211_CMD_GET_MPATH,
@@ -5316,30 +4585,40 @@ static struct genl_ops nl80211_ops[] = {
5316 .dumpit = nl80211_dump_mpath, 4585 .dumpit = nl80211_dump_mpath,
5317 .policy = nl80211_policy, 4586 .policy = nl80211_policy,
5318 .flags = GENL_ADMIN_PERM, 4587 .flags = GENL_ADMIN_PERM,
4588 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4589 NL80211_FLAG_NEED_RTNL,
5319 }, 4590 },
5320 { 4591 {
5321 .cmd = NL80211_CMD_SET_MPATH, 4592 .cmd = NL80211_CMD_SET_MPATH,
5322 .doit = nl80211_set_mpath, 4593 .doit = nl80211_set_mpath,
5323 .policy = nl80211_policy, 4594 .policy = nl80211_policy,
5324 .flags = GENL_ADMIN_PERM, 4595 .flags = GENL_ADMIN_PERM,
4596 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4597 NL80211_FLAG_NEED_RTNL,
5325 }, 4598 },
5326 { 4599 {
5327 .cmd = NL80211_CMD_NEW_MPATH, 4600 .cmd = NL80211_CMD_NEW_MPATH,
5328 .doit = nl80211_new_mpath, 4601 .doit = nl80211_new_mpath,
5329 .policy = nl80211_policy, 4602 .policy = nl80211_policy,
5330 .flags = GENL_ADMIN_PERM, 4603 .flags = GENL_ADMIN_PERM,
4604 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4605 NL80211_FLAG_NEED_RTNL,
5331 }, 4606 },
5332 { 4607 {
5333 .cmd = NL80211_CMD_DEL_MPATH, 4608 .cmd = NL80211_CMD_DEL_MPATH,
5334 .doit = nl80211_del_mpath, 4609 .doit = nl80211_del_mpath,
5335 .policy = nl80211_policy, 4610 .policy = nl80211_policy,
5336 .flags = GENL_ADMIN_PERM, 4611 .flags = GENL_ADMIN_PERM,
4612 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4613 NL80211_FLAG_NEED_RTNL,
5337 }, 4614 },
5338 { 4615 {
5339 .cmd = NL80211_CMD_SET_BSS, 4616 .cmd = NL80211_CMD_SET_BSS,
5340 .doit = nl80211_set_bss, 4617 .doit = nl80211_set_bss,
5341 .policy = nl80211_policy, 4618 .policy = nl80211_policy,
5342 .flags = GENL_ADMIN_PERM, 4619 .flags = GENL_ADMIN_PERM,
4620 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4621 NL80211_FLAG_NEED_RTNL,
5343 }, 4622 },
5344 { 4623 {
5345 .cmd = NL80211_CMD_GET_REG, 4624 .cmd = NL80211_CMD_GET_REG,
@@ -5364,18 +4643,24 @@ static struct genl_ops nl80211_ops[] = {
5364 .doit = nl80211_get_mesh_params, 4643 .doit = nl80211_get_mesh_params,
5365 .policy = nl80211_policy, 4644 .policy = nl80211_policy,
5366 /* can be retrieved by unprivileged users */ 4645 /* can be retrieved by unprivileged users */
4646 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4647 NL80211_FLAG_NEED_RTNL,
5367 }, 4648 },
5368 { 4649 {
5369 .cmd = NL80211_CMD_SET_MESH_PARAMS, 4650 .cmd = NL80211_CMD_SET_MESH_PARAMS,
5370 .doit = nl80211_set_mesh_params, 4651 .doit = nl80211_set_mesh_params,
5371 .policy = nl80211_policy, 4652 .policy = nl80211_policy,
5372 .flags = GENL_ADMIN_PERM, 4653 .flags = GENL_ADMIN_PERM,
4654 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4655 NL80211_FLAG_NEED_RTNL,
5373 }, 4656 },
5374 { 4657 {
5375 .cmd = NL80211_CMD_TRIGGER_SCAN, 4658 .cmd = NL80211_CMD_TRIGGER_SCAN,
5376 .doit = nl80211_trigger_scan, 4659 .doit = nl80211_trigger_scan,
5377 .policy = nl80211_policy, 4660 .policy = nl80211_policy,
5378 .flags = GENL_ADMIN_PERM, 4661 .flags = GENL_ADMIN_PERM,
4662 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4663 NL80211_FLAG_NEED_RTNL,
5379 }, 4664 },
5380 { 4665 {
5381 .cmd = NL80211_CMD_GET_SCAN, 4666 .cmd = NL80211_CMD_GET_SCAN,
@@ -5387,36 +4672,48 @@ static struct genl_ops nl80211_ops[] = {
5387 .doit = nl80211_authenticate, 4672 .doit = nl80211_authenticate,
5388 .policy = nl80211_policy, 4673 .policy = nl80211_policy,
5389 .flags = GENL_ADMIN_PERM, 4674 .flags = GENL_ADMIN_PERM,
4675 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4676 NL80211_FLAG_NEED_RTNL,
5390 }, 4677 },
5391 { 4678 {
5392 .cmd = NL80211_CMD_ASSOCIATE, 4679 .cmd = NL80211_CMD_ASSOCIATE,
5393 .doit = nl80211_associate, 4680 .doit = nl80211_associate,
5394 .policy = nl80211_policy, 4681 .policy = nl80211_policy,
5395 .flags = GENL_ADMIN_PERM, 4682 .flags = GENL_ADMIN_PERM,
4683 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4684 NL80211_FLAG_NEED_RTNL,
5396 }, 4685 },
5397 { 4686 {
5398 .cmd = NL80211_CMD_DEAUTHENTICATE, 4687 .cmd = NL80211_CMD_DEAUTHENTICATE,
5399 .doit = nl80211_deauthenticate, 4688 .doit = nl80211_deauthenticate,
5400 .policy = nl80211_policy, 4689 .policy = nl80211_policy,
5401 .flags = GENL_ADMIN_PERM, 4690 .flags = GENL_ADMIN_PERM,
4691 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4692 NL80211_FLAG_NEED_RTNL,
5402 }, 4693 },
5403 { 4694 {
5404 .cmd = NL80211_CMD_DISASSOCIATE, 4695 .cmd = NL80211_CMD_DISASSOCIATE,
5405 .doit = nl80211_disassociate, 4696 .doit = nl80211_disassociate,
5406 .policy = nl80211_policy, 4697 .policy = nl80211_policy,
5407 .flags = GENL_ADMIN_PERM, 4698 .flags = GENL_ADMIN_PERM,
4699 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4700 NL80211_FLAG_NEED_RTNL,
5408 }, 4701 },
5409 { 4702 {
5410 .cmd = NL80211_CMD_JOIN_IBSS, 4703 .cmd = NL80211_CMD_JOIN_IBSS,
5411 .doit = nl80211_join_ibss, 4704 .doit = nl80211_join_ibss,
5412 .policy = nl80211_policy, 4705 .policy = nl80211_policy,
5413 .flags = GENL_ADMIN_PERM, 4706 .flags = GENL_ADMIN_PERM,
4707 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4708 NL80211_FLAG_NEED_RTNL,
5414 }, 4709 },
5415 { 4710 {
5416 .cmd = NL80211_CMD_LEAVE_IBSS, 4711 .cmd = NL80211_CMD_LEAVE_IBSS,
5417 .doit = nl80211_leave_ibss, 4712 .doit = nl80211_leave_ibss,
5418 .policy = nl80211_policy, 4713 .policy = nl80211_policy,
5419 .flags = GENL_ADMIN_PERM, 4714 .flags = GENL_ADMIN_PERM,
4715 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4716 NL80211_FLAG_NEED_RTNL,
5420 }, 4717 },
5421#ifdef CONFIG_NL80211_TESTMODE 4718#ifdef CONFIG_NL80211_TESTMODE
5422 { 4719 {
@@ -5424,6 +4721,8 @@ static struct genl_ops nl80211_ops[] = {
5424 .doit = nl80211_testmode_do, 4721 .doit = nl80211_testmode_do,
5425 .policy = nl80211_policy, 4722 .policy = nl80211_policy,
5426 .flags = GENL_ADMIN_PERM, 4723 .flags = GENL_ADMIN_PERM,
4724 .internal_flags = NL80211_FLAG_NEED_WIPHY |
4725 NL80211_FLAG_NEED_RTNL,
5427 }, 4726 },
5428#endif 4727#endif
5429 { 4728 {
@@ -5431,18 +4730,24 @@ static struct genl_ops nl80211_ops[] = {
5431 .doit = nl80211_connect, 4730 .doit = nl80211_connect,
5432 .policy = nl80211_policy, 4731 .policy = nl80211_policy,
5433 .flags = GENL_ADMIN_PERM, 4732 .flags = GENL_ADMIN_PERM,
4733 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4734 NL80211_FLAG_NEED_RTNL,
5434 }, 4735 },
5435 { 4736 {
5436 .cmd = NL80211_CMD_DISCONNECT, 4737 .cmd = NL80211_CMD_DISCONNECT,
5437 .doit = nl80211_disconnect, 4738 .doit = nl80211_disconnect,
5438 .policy = nl80211_policy, 4739 .policy = nl80211_policy,
5439 .flags = GENL_ADMIN_PERM, 4740 .flags = GENL_ADMIN_PERM,
4741 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4742 NL80211_FLAG_NEED_RTNL,
5440 }, 4743 },
5441 { 4744 {
5442 .cmd = NL80211_CMD_SET_WIPHY_NETNS, 4745 .cmd = NL80211_CMD_SET_WIPHY_NETNS,
5443 .doit = nl80211_wiphy_netns, 4746 .doit = nl80211_wiphy_netns,
5444 .policy = nl80211_policy, 4747 .policy = nl80211_policy,
5445 .flags = GENL_ADMIN_PERM, 4748 .flags = GENL_ADMIN_PERM,
4749 .internal_flags = NL80211_FLAG_NEED_WIPHY |
4750 NL80211_FLAG_NEED_RTNL,
5446 }, 4751 },
5447 { 4752 {
5448 .cmd = NL80211_CMD_GET_SURVEY, 4753 .cmd = NL80211_CMD_GET_SURVEY,
@@ -5454,72 +4759,96 @@ static struct genl_ops nl80211_ops[] = {
5454 .doit = nl80211_setdel_pmksa, 4759 .doit = nl80211_setdel_pmksa,
5455 .policy = nl80211_policy, 4760 .policy = nl80211_policy,
5456 .flags = GENL_ADMIN_PERM, 4761 .flags = GENL_ADMIN_PERM,
4762 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4763 NL80211_FLAG_NEED_RTNL,
5457 }, 4764 },
5458 { 4765 {
5459 .cmd = NL80211_CMD_DEL_PMKSA, 4766 .cmd = NL80211_CMD_DEL_PMKSA,
5460 .doit = nl80211_setdel_pmksa, 4767 .doit = nl80211_setdel_pmksa,
5461 .policy = nl80211_policy, 4768 .policy = nl80211_policy,
5462 .flags = GENL_ADMIN_PERM, 4769 .flags = GENL_ADMIN_PERM,
4770 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4771 NL80211_FLAG_NEED_RTNL,
5463 }, 4772 },
5464 { 4773 {
5465 .cmd = NL80211_CMD_FLUSH_PMKSA, 4774 .cmd = NL80211_CMD_FLUSH_PMKSA,
5466 .doit = nl80211_flush_pmksa, 4775 .doit = nl80211_flush_pmksa,
5467 .policy = nl80211_policy, 4776 .policy = nl80211_policy,
5468 .flags = GENL_ADMIN_PERM, 4777 .flags = GENL_ADMIN_PERM,
4778 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4779 NL80211_FLAG_NEED_RTNL,
5469 }, 4780 },
5470 { 4781 {
5471 .cmd = NL80211_CMD_REMAIN_ON_CHANNEL, 4782 .cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
5472 .doit = nl80211_remain_on_channel, 4783 .doit = nl80211_remain_on_channel,
5473 .policy = nl80211_policy, 4784 .policy = nl80211_policy,
5474 .flags = GENL_ADMIN_PERM, 4785 .flags = GENL_ADMIN_PERM,
4786 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4787 NL80211_FLAG_NEED_RTNL,
5475 }, 4788 },
5476 { 4789 {
5477 .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, 4790 .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
5478 .doit = nl80211_cancel_remain_on_channel, 4791 .doit = nl80211_cancel_remain_on_channel,
5479 .policy = nl80211_policy, 4792 .policy = nl80211_policy,
5480 .flags = GENL_ADMIN_PERM, 4793 .flags = GENL_ADMIN_PERM,
4794 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4795 NL80211_FLAG_NEED_RTNL,
5481 }, 4796 },
5482 { 4797 {
5483 .cmd = NL80211_CMD_SET_TX_BITRATE_MASK, 4798 .cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
5484 .doit = nl80211_set_tx_bitrate_mask, 4799 .doit = nl80211_set_tx_bitrate_mask,
5485 .policy = nl80211_policy, 4800 .policy = nl80211_policy,
5486 .flags = GENL_ADMIN_PERM, 4801 .flags = GENL_ADMIN_PERM,
4802 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4803 NL80211_FLAG_NEED_RTNL,
5487 }, 4804 },
5488 { 4805 {
5489 .cmd = NL80211_CMD_REGISTER_FRAME, 4806 .cmd = NL80211_CMD_REGISTER_FRAME,
5490 .doit = nl80211_register_mgmt, 4807 .doit = nl80211_register_mgmt,
5491 .policy = nl80211_policy, 4808 .policy = nl80211_policy,
5492 .flags = GENL_ADMIN_PERM, 4809 .flags = GENL_ADMIN_PERM,
4810 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4811 NL80211_FLAG_NEED_RTNL,
5493 }, 4812 },
5494 { 4813 {
5495 .cmd = NL80211_CMD_FRAME, 4814 .cmd = NL80211_CMD_FRAME,
5496 .doit = nl80211_tx_mgmt, 4815 .doit = nl80211_tx_mgmt,
5497 .policy = nl80211_policy, 4816 .policy = nl80211_policy,
5498 .flags = GENL_ADMIN_PERM, 4817 .flags = GENL_ADMIN_PERM,
4818 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4819 NL80211_FLAG_NEED_RTNL,
5499 }, 4820 },
5500 { 4821 {
5501 .cmd = NL80211_CMD_SET_POWER_SAVE, 4822 .cmd = NL80211_CMD_SET_POWER_SAVE,
5502 .doit = nl80211_set_power_save, 4823 .doit = nl80211_set_power_save,
5503 .policy = nl80211_policy, 4824 .policy = nl80211_policy,
5504 .flags = GENL_ADMIN_PERM, 4825 .flags = GENL_ADMIN_PERM,
4826 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4827 NL80211_FLAG_NEED_RTNL,
5505 }, 4828 },
5506 { 4829 {
5507 .cmd = NL80211_CMD_GET_POWER_SAVE, 4830 .cmd = NL80211_CMD_GET_POWER_SAVE,
5508 .doit = nl80211_get_power_save, 4831 .doit = nl80211_get_power_save,
5509 .policy = nl80211_policy, 4832 .policy = nl80211_policy,
5510 /* can be retrieved by unprivileged users */ 4833 /* can be retrieved by unprivileged users */
4834 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4835 NL80211_FLAG_NEED_RTNL,
5511 }, 4836 },
5512 { 4837 {
5513 .cmd = NL80211_CMD_SET_CQM, 4838 .cmd = NL80211_CMD_SET_CQM,
5514 .doit = nl80211_set_cqm, 4839 .doit = nl80211_set_cqm,
5515 .policy = nl80211_policy, 4840 .policy = nl80211_policy,
5516 .flags = GENL_ADMIN_PERM, 4841 .flags = GENL_ADMIN_PERM,
4842 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4843 NL80211_FLAG_NEED_RTNL,
5517 }, 4844 },
5518 { 4845 {
5519 .cmd = NL80211_CMD_SET_CHANNEL, 4846 .cmd = NL80211_CMD_SET_CHANNEL,
5520 .doit = nl80211_set_channel, 4847 .doit = nl80211_set_channel,
5521 .policy = nl80211_policy, 4848 .policy = nl80211_policy,
5522 .flags = GENL_ADMIN_PERM, 4849 .flags = GENL_ADMIN_PERM,
4850 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4851 NL80211_FLAG_NEED_RTNL,
5523 }, 4852 },
5524 { 4853 {
5525 .cmd = NL80211_CMD_SET_WDS_PEER, 4854 .cmd = NL80211_CMD_SET_WDS_PEER,