aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-06-28 13:18:21 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-06-28 13:18:21 -0400
commit57ed5cd695d7373b8ae0ae9f10fe945e774d58f0 (patch)
tree7ee6244ea7c0be81a541d4e57783f83c4dfd7d66 /net/wireless/nl80211.c
parent5e6700b3bf98fe98d630bf9c939ad4c85ce95592 (diff)
parent0f817ed52d07873cd39c9d3f6d87fae962dc742f (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts: net/wireless/nl80211.c
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c287
1 files changed, 160 insertions, 127 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e545023e2871..1cc47aca7f05 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1111,10 +1111,16 @@ nl80211_send_mgmt_stypes(struct sk_buff *msg,
1111 return 0; 1111 return 0;
1112} 1112}
1113 1113
1114struct nl80211_dump_wiphy_state {
1115 s64 filter_wiphy;
1116 long start;
1117 long split_start, band_start, chan_start;
1118 bool split;
1119};
1120
1114static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, 1121static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1115 struct sk_buff *msg, u32 portid, u32 seq, 1122 struct sk_buff *msg, u32 portid, u32 seq,
1116 int flags, bool split, long *split_start, 1123 int flags, struct nl80211_dump_wiphy_state *state)
1117 long *band_start, long *chan_start)
1118{ 1124{
1119 void *hdr; 1125 void *hdr;
1120 struct nlattr *nl_bands, *nl_band; 1126 struct nlattr *nl_bands, *nl_band;
@@ -1125,19 +1131,14 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1125 int i; 1131 int i;
1126 const struct ieee80211_txrx_stypes *mgmt_stypes = 1132 const struct ieee80211_txrx_stypes *mgmt_stypes =
1127 dev->wiphy.mgmt_stypes; 1133 dev->wiphy.mgmt_stypes;
1128 long start = 0, start_chan = 0, start_band = 0;
1129 u32 features; 1134 u32 features;
1130 1135
1131 hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY); 1136 hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY);
1132 if (!hdr) 1137 if (!hdr)
1133 return -ENOBUFS; 1138 return -ENOBUFS;
1134 1139
1135 /* allow always using the variables */ 1140 if (WARN_ON(!state))
1136 if (!split) { 1141 return -EINVAL;
1137 split_start = &start;
1138 band_start = &start_band;
1139 chan_start = &start_chan;
1140 }
1141 1142
1142 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) || 1143 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) ||
1143 nla_put_string(msg, NL80211_ATTR_WIPHY_NAME, 1144 nla_put_string(msg, NL80211_ATTR_WIPHY_NAME,
@@ -1146,7 +1147,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1146 cfg80211_rdev_list_generation)) 1147 cfg80211_rdev_list_generation))
1147 goto nla_put_failure; 1148 goto nla_put_failure;
1148 1149
1149 switch (*split_start) { 1150 switch (state->split_start) {
1150 case 0: 1151 case 0:
1151 if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, 1152 if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
1152 dev->wiphy.retry_short) || 1153 dev->wiphy.retry_short) ||
@@ -1188,9 +1189,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1188 if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && 1189 if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
1189 nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) 1190 nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
1190 goto nla_put_failure; 1191 goto nla_put_failure;
1192 if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
1193 nla_put_flag(msg, WIPHY_FLAG_SUPPORTS_5_10_MHZ))
1194 goto nla_put_failure;
1191 1195
1192 (*split_start)++; 1196 state->split_start++;
1193 if (split) 1197 if (state->split)
1194 break; 1198 break;
1195 case 1: 1199 case 1:
1196 if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES, 1200 if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES,
@@ -1234,22 +1238,23 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1234 } 1238 }
1235 } 1239 }
1236 1240
1237 (*split_start)++; 1241 state->split_start++;
1238 if (split) 1242 if (state->split)
1239 break; 1243 break;
1240 case 2: 1244 case 2:
1241 if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES, 1245 if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES,
1242 dev->wiphy.interface_modes)) 1246 dev->wiphy.interface_modes))
1243 goto nla_put_failure; 1247 goto nla_put_failure;
1244 (*split_start)++; 1248 state->split_start++;
1245 if (split) 1249 if (state->split)
1246 break; 1250 break;
1247 case 3: 1251 case 3:
1248 nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); 1252 nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
1249 if (!nl_bands) 1253 if (!nl_bands)
1250 goto nla_put_failure; 1254 goto nla_put_failure;
1251 1255
1252 for (band = *band_start; band < IEEE80211_NUM_BANDS; band++) { 1256 for (band = state->band_start;
1257 band < IEEE80211_NUM_BANDS; band++) {
1253 struct ieee80211_supported_band *sband; 1258 struct ieee80211_supported_band *sband;
1254 1259
1255 sband = dev->wiphy.bands[band]; 1260 sband = dev->wiphy.bands[band];
@@ -1261,12 +1266,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1261 if (!nl_band) 1266 if (!nl_band)
1262 goto nla_put_failure; 1267 goto nla_put_failure;
1263 1268
1264 switch (*chan_start) { 1269 switch (state->chan_start) {
1265 case 0: 1270 case 0:
1266 if (nl80211_send_band_rateinfo(msg, sband)) 1271 if (nl80211_send_band_rateinfo(msg, sband))
1267 goto nla_put_failure; 1272 goto nla_put_failure;
1268 (*chan_start)++; 1273 state->chan_start++;
1269 if (split) 1274 if (state->split)
1270 break; 1275 break;
1271 default: 1276 default:
1272 /* add frequencies */ 1277 /* add frequencies */
@@ -1275,7 +1280,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1275 if (!nl_freqs) 1280 if (!nl_freqs)
1276 goto nla_put_failure; 1281 goto nla_put_failure;
1277 1282
1278 for (i = *chan_start - 1; 1283 for (i = state->chan_start - 1;
1279 i < sband->n_channels; 1284 i < sband->n_channels;
1280 i++) { 1285 i++) {
1281 nl_freq = nla_nest_start(msg, i); 1286 nl_freq = nla_nest_start(msg, i);
@@ -1284,26 +1289,27 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1284 1289
1285 chan = &sband->channels[i]; 1290 chan = &sband->channels[i];
1286 1291
1287 if (nl80211_msg_put_channel(msg, chan, 1292 if (nl80211_msg_put_channel(
1288 split)) 1293 msg, chan,
1294 state->split))
1289 goto nla_put_failure; 1295 goto nla_put_failure;
1290 1296
1291 nla_nest_end(msg, nl_freq); 1297 nla_nest_end(msg, nl_freq);
1292 if (split) 1298 if (state->split)
1293 break; 1299 break;
1294 } 1300 }
1295 if (i < sband->n_channels) 1301 if (i < sband->n_channels)
1296 *chan_start = i + 2; 1302 state->chan_start = i + 2;
1297 else 1303 else
1298 *chan_start = 0; 1304 state->chan_start = 0;
1299 nla_nest_end(msg, nl_freqs); 1305 nla_nest_end(msg, nl_freqs);
1300 } 1306 }
1301 1307
1302 nla_nest_end(msg, nl_band); 1308 nla_nest_end(msg, nl_band);
1303 1309
1304 if (split) { 1310 if (state->split) {
1305 /* start again here */ 1311 /* start again here */
1306 if (*chan_start) 1312 if (state->chan_start)
1307 band--; 1313 band--;
1308 break; 1314 break;
1309 } 1315 }
@@ -1311,14 +1317,14 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1311 nla_nest_end(msg, nl_bands); 1317 nla_nest_end(msg, nl_bands);
1312 1318
1313 if (band < IEEE80211_NUM_BANDS) 1319 if (band < IEEE80211_NUM_BANDS)
1314 *band_start = band + 1; 1320 state->band_start = band + 1;
1315 else 1321 else
1316 *band_start = 0; 1322 state->band_start = 0;
1317 1323
1318 /* if bands & channels are done, continue outside */ 1324 /* if bands & channels are done, continue outside */
1319 if (*band_start == 0 && *chan_start == 0) 1325 if (state->band_start == 0 && state->chan_start == 0)
1320 (*split_start)++; 1326 state->split_start++;
1321 if (split) 1327 if (state->split)
1322 break; 1328 break;
1323 case 4: 1329 case 4:
1324 nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS); 1330 nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS);
@@ -1384,7 +1390,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1384 } 1390 }
1385 CMD(start_p2p_device, START_P2P_DEVICE); 1391 CMD(start_p2p_device, START_P2P_DEVICE);
1386 CMD(set_mcast_rate, SET_MCAST_RATE); 1392 CMD(set_mcast_rate, SET_MCAST_RATE);
1387 if (split) { 1393 if (state->split) {
1388 CMD(crit_proto_start, CRIT_PROTOCOL_START); 1394 CMD(crit_proto_start, CRIT_PROTOCOL_START);
1389 CMD(crit_proto_stop, CRIT_PROTOCOL_STOP); 1395 CMD(crit_proto_stop, CRIT_PROTOCOL_STOP);
1390 } 1396 }
@@ -1408,8 +1414,8 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1408 } 1414 }
1409 1415
1410 nla_nest_end(msg, nl_cmds); 1416 nla_nest_end(msg, nl_cmds);
1411 (*split_start)++; 1417 state->split_start++;
1412 if (split) 1418 if (state->split)
1413 break; 1419 break;
1414 case 5: 1420 case 5:
1415 if (dev->ops->remain_on_channel && 1421 if (dev->ops->remain_on_channel &&
@@ -1425,29 +1431,30 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1425 1431
1426 if (nl80211_send_mgmt_stypes(msg, mgmt_stypes)) 1432 if (nl80211_send_mgmt_stypes(msg, mgmt_stypes))
1427 goto nla_put_failure; 1433 goto nla_put_failure;
1428 (*split_start)++; 1434 state->split_start++;
1429 if (split) 1435 if (state->split)
1430 break; 1436 break;
1431 case 6: 1437 case 6:
1432#ifdef CONFIG_PM 1438#ifdef CONFIG_PM
1433 if (nl80211_send_wowlan(msg, dev, split)) 1439 if (nl80211_send_wowlan(msg, dev, state->split))
1434 goto nla_put_failure; 1440 goto nla_put_failure;
1435 (*split_start)++; 1441 state->split_start++;
1436 if (split) 1442 if (state->split)
1437 break; 1443 break;
1438#else 1444#else
1439 (*split_start)++; 1445 state->split_start++;
1440#endif 1446#endif
1441 case 7: 1447 case 7:
1442 if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, 1448 if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
1443 dev->wiphy.software_iftypes)) 1449 dev->wiphy.software_iftypes))
1444 goto nla_put_failure; 1450 goto nla_put_failure;
1445 1451
1446 if (nl80211_put_iface_combinations(&dev->wiphy, msg, split)) 1452 if (nl80211_put_iface_combinations(&dev->wiphy, msg,
1453 state->split))
1447 goto nla_put_failure; 1454 goto nla_put_failure;
1448 1455
1449 (*split_start)++; 1456 state->split_start++;
1450 if (split) 1457 if (state->split)
1451 break; 1458 break;
1452 case 8: 1459 case 8:
1453 if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) && 1460 if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) &&
@@ -1461,7 +1468,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1461 * dump is split, otherwise it makes it too big. Therefore 1468 * dump is split, otherwise it makes it too big. Therefore
1462 * only advertise it in that case. 1469 * only advertise it in that case.
1463 */ 1470 */
1464 if (split) 1471 if (state->split)
1465 features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS; 1472 features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS;
1466 if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features)) 1473 if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features))
1467 goto nla_put_failure; 1474 goto nla_put_failure;
@@ -1488,7 +1495,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1488 * case we'll continue with more data in the next round, 1495 * case we'll continue with more data in the next round,
1489 * but break unconditionally so unsplit data stops here. 1496 * but break unconditionally so unsplit data stops here.
1490 */ 1497 */
1491 (*split_start)++; 1498 state->split_start++;
1492 break; 1499 break;
1493 case 9: 1500 case 9:
1494 if (dev->wiphy.extended_capabilities && 1501 if (dev->wiphy.extended_capabilities &&
@@ -1507,7 +1514,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1507 goto nla_put_failure; 1514 goto nla_put_failure;
1508 1515
1509 /* done */ 1516 /* done */
1510 *split_start = 0; 1517 state->split_start = 0;
1511 break; 1518 break;
1512 } 1519 }
1513 return genlmsg_end(msg, hdr); 1520 return genlmsg_end(msg, hdr);
@@ -1517,67 +1524,78 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1517 return -EMSGSIZE; 1524 return -EMSGSIZE;
1518} 1525}
1519 1526
1527static int nl80211_dump_wiphy_parse(struct sk_buff *skb,
1528 struct netlink_callback *cb,
1529 struct nl80211_dump_wiphy_state *state)
1530{
1531 struct nlattr **tb = nl80211_fam.attrbuf;
1532 int ret = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
1533 tb, nl80211_fam.maxattr, nl80211_policy);
1534 /* ignore parse errors for backward compatibility */
1535 if (ret)
1536 return 0;
1537
1538 state->split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP];
1539 if (tb[NL80211_ATTR_WIPHY])
1540 state->filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
1541 if (tb[NL80211_ATTR_WDEV])
1542 state->filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32;
1543 if (tb[NL80211_ATTR_IFINDEX]) {
1544 struct net_device *netdev;
1545 struct cfg80211_registered_device *rdev;
1546 int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
1547
1548 netdev = dev_get_by_index(sock_net(skb->sk), ifidx);
1549 if (!netdev)
1550 return -ENODEV;
1551 if (netdev->ieee80211_ptr) {
1552 rdev = wiphy_to_dev(
1553 netdev->ieee80211_ptr->wiphy);
1554 state->filter_wiphy = rdev->wiphy_idx;
1555 }
1556 dev_put(netdev);
1557 }
1558
1559 return 0;
1560}
1561
1520static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) 1562static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1521{ 1563{
1522 int idx = 0, ret; 1564 int idx = 0, ret;
1523 int start = cb->args[0]; 1565 struct nl80211_dump_wiphy_state *state = (void *)cb->args[0];
1524 struct cfg80211_registered_device *dev; 1566 struct cfg80211_registered_device *dev;
1525 s64 filter_wiphy = -1;
1526 bool split = false;
1527 struct nlattr **tb;
1528 int res;
1529
1530 /* will be zeroed in nlmsg_parse() */
1531 tb = kmalloc(sizeof(*tb) * (NL80211_ATTR_MAX + 1), GFP_KERNEL);
1532 if (!tb)
1533 return -ENOMEM;
1534 1567
1535 rtnl_lock(); 1568 rtnl_lock();
1536 1569 if (!state) {
1537 res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, 1570 state = kzalloc(sizeof(*state), GFP_KERNEL);
1538 tb, NL80211_ATTR_MAX, nl80211_policy); 1571 if (!state) {
1539 if (res == 0) { 1572 rtnl_unlock();
1540 split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP]; 1573 return -ENOMEM;
1541 if (tb[NL80211_ATTR_WIPHY])
1542 filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
1543 if (tb[NL80211_ATTR_WDEV])
1544 filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32;
1545 if (tb[NL80211_ATTR_IFINDEX]) {
1546 struct net_device *netdev;
1547 int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
1548
1549 netdev = dev_get_by_index(sock_net(skb->sk), ifidx);
1550 if (!netdev) {
1551 rtnl_unlock();
1552 kfree(tb);
1553 return -ENODEV;
1554 }
1555 if (netdev->ieee80211_ptr) {
1556 dev = wiphy_to_dev(
1557 netdev->ieee80211_ptr->wiphy);
1558 filter_wiphy = dev->wiphy_idx;
1559 }
1560 dev_put(netdev);
1561 } 1574 }
1575 state->filter_wiphy = -1;
1576 ret = nl80211_dump_wiphy_parse(skb, cb, state);
1577 if (ret) {
1578 kfree(state);
1579 rtnl_unlock();
1580 return ret;
1581 }
1582 cb->args[0] = (long)state;
1562 } 1583 }
1563 kfree(tb);
1564 1584
1565 list_for_each_entry(dev, &cfg80211_rdev_list, list) { 1585 list_for_each_entry(dev, &cfg80211_rdev_list, list) {
1566 if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) 1586 if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk)))
1567 continue; 1587 continue;
1568 if (++idx <= start) 1588 if (++idx <= state->start)
1569 continue; 1589 continue;
1570 if (filter_wiphy != -1 && dev->wiphy_idx != filter_wiphy) 1590 if (state->filter_wiphy != -1 &&
1591 state->filter_wiphy != dev->wiphy_idx)
1571 continue; 1592 continue;
1572 /* attempt to fit multiple wiphy data chunks into the skb */ 1593 /* attempt to fit multiple wiphy data chunks into the skb */
1573 do { 1594 do {
1574 ret = nl80211_send_wiphy(dev, skb, 1595 ret = nl80211_send_wiphy(dev, skb,
1575 NETLINK_CB(cb->skb).portid, 1596 NETLINK_CB(cb->skb).portid,
1576 cb->nlh->nlmsg_seq, 1597 cb->nlh->nlmsg_seq,
1577 NLM_F_MULTI, 1598 NLM_F_MULTI, state);
1578 split, &cb->args[1],
1579 &cb->args[2],
1580 &cb->args[3]);
1581 if (ret < 0) { 1599 if (ret < 0) {
1582 /* 1600 /*
1583 * If sending the wiphy data didn't fit (ENOBUFS 1601 * If sending the wiphy data didn't fit (ENOBUFS
@@ -1602,27 +1620,34 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1602 idx--; 1620 idx--;
1603 break; 1621 break;
1604 } 1622 }
1605 } while (cb->args[1] > 0); 1623 } while (state->split_start > 0);
1606 break; 1624 break;
1607 } 1625 }
1608 rtnl_unlock(); 1626 rtnl_unlock();
1609 1627
1610 cb->args[0] = idx; 1628 state->start = idx;
1611 1629
1612 return skb->len; 1630 return skb->len;
1613} 1631}
1614 1632
1633static int nl80211_dump_wiphy_done(struct netlink_callback *cb)
1634{
1635 kfree((void *)cb->args[0]);
1636 return 0;
1637}
1638
1615static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) 1639static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
1616{ 1640{
1617 struct sk_buff *msg; 1641 struct sk_buff *msg;
1618 struct cfg80211_registered_device *dev = info->user_ptr[0]; 1642 struct cfg80211_registered_device *dev = info->user_ptr[0];
1643 struct nl80211_dump_wiphy_state state = {};
1619 1644
1620 msg = nlmsg_new(4096, GFP_KERNEL); 1645 msg = nlmsg_new(4096, GFP_KERNEL);
1621 if (!msg) 1646 if (!msg)
1622 return -ENOMEM; 1647 return -ENOMEM;
1623 1648
1624 if (nl80211_send_wiphy(dev, msg, info->snd_portid, info->snd_seq, 0, 1649 if (nl80211_send_wiphy(dev, msg, info->snd_portid, info->snd_seq, 0,
1625 false, NULL, NULL, NULL) < 0) { 1650 &state) < 0) {
1626 nlmsg_free(msg); 1651 nlmsg_free(msg);
1627 return -ENOBUFS; 1652 return -ENOBUFS;
1628 } 1653 }
@@ -1739,6 +1764,11 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
1739 IEEE80211_CHAN_DISABLED)) 1764 IEEE80211_CHAN_DISABLED))
1740 return -EINVAL; 1765 return -EINVAL;
1741 1766
1767 if ((chandef->width == NL80211_CHAN_WIDTH_5 ||
1768 chandef->width == NL80211_CHAN_WIDTH_10) &&
1769 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ))
1770 return -EINVAL;
1771
1742 return 0; 1772 return 0;
1743} 1773}
1744 1774
@@ -2890,61 +2920,58 @@ static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info)
2890 return err; 2920 return err;
2891} 2921}
2892 2922
2893static int nl80211_parse_beacon(struct genl_info *info, 2923static int nl80211_parse_beacon(struct nlattr *attrs[],
2894 struct cfg80211_beacon_data *bcn) 2924 struct cfg80211_beacon_data *bcn)
2895{ 2925{
2896 bool haveinfo = false; 2926 bool haveinfo = false;
2897 2927
2898 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL]) || 2928 if (!is_valid_ie_attr(attrs[NL80211_ATTR_BEACON_TAIL]) ||
2899 !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]) || 2929 !is_valid_ie_attr(attrs[NL80211_ATTR_IE]) ||
2900 !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE_PROBE_RESP]) || 2930 !is_valid_ie_attr(attrs[NL80211_ATTR_IE_PROBE_RESP]) ||
2901 !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE_ASSOC_RESP])) 2931 !is_valid_ie_attr(attrs[NL80211_ATTR_IE_ASSOC_RESP]))
2902 return -EINVAL; 2932 return -EINVAL;
2903 2933
2904 memset(bcn, 0, sizeof(*bcn)); 2934 memset(bcn, 0, sizeof(*bcn));
2905 2935
2906 if (info->attrs[NL80211_ATTR_BEACON_HEAD]) { 2936 if (attrs[NL80211_ATTR_BEACON_HEAD]) {
2907 bcn->head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]); 2937 bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]);
2908 bcn->head_len = nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]); 2938 bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]);
2909 if (!bcn->head_len) 2939 if (!bcn->head_len)
2910 return -EINVAL; 2940 return -EINVAL;
2911 haveinfo = true; 2941 haveinfo = true;
2912 } 2942 }
2913 2943
2914 if (info->attrs[NL80211_ATTR_BEACON_TAIL]) { 2944 if (attrs[NL80211_ATTR_BEACON_TAIL]) {
2915 bcn->tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]); 2945 bcn->tail = nla_data(attrs[NL80211_ATTR_BEACON_TAIL]);
2916 bcn->tail_len = 2946 bcn->tail_len = nla_len(attrs[NL80211_ATTR_BEACON_TAIL]);
2917 nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]);
2918 haveinfo = true; 2947 haveinfo = true;
2919 } 2948 }
2920 2949
2921 if (!haveinfo) 2950 if (!haveinfo)
2922 return -EINVAL; 2951 return -EINVAL;
2923 2952
2924 if (info->attrs[NL80211_ATTR_IE]) { 2953 if (attrs[NL80211_ATTR_IE]) {
2925 bcn->beacon_ies = nla_data(info->attrs[NL80211_ATTR_IE]); 2954 bcn->beacon_ies = nla_data(attrs[NL80211_ATTR_IE]);
2926 bcn->beacon_ies_len = nla_len(info->attrs[NL80211_ATTR_IE]); 2955 bcn->beacon_ies_len = nla_len(attrs[NL80211_ATTR_IE]);
2927 } 2956 }
2928 2957
2929 if (info->attrs[NL80211_ATTR_IE_PROBE_RESP]) { 2958 if (attrs[NL80211_ATTR_IE_PROBE_RESP]) {
2930 bcn->proberesp_ies = 2959 bcn->proberesp_ies =
2931 nla_data(info->attrs[NL80211_ATTR_IE_PROBE_RESP]); 2960 nla_data(attrs[NL80211_ATTR_IE_PROBE_RESP]);
2932 bcn->proberesp_ies_len = 2961 bcn->proberesp_ies_len =
2933 nla_len(info->attrs[NL80211_ATTR_IE_PROBE_RESP]); 2962 nla_len(attrs[NL80211_ATTR_IE_PROBE_RESP]);
2934 } 2963 }
2935 2964
2936 if (info->attrs[NL80211_ATTR_IE_ASSOC_RESP]) { 2965 if (attrs[NL80211_ATTR_IE_ASSOC_RESP]) {
2937 bcn->assocresp_ies = 2966 bcn->assocresp_ies =
2938 nla_data(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]); 2967 nla_data(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
2939 bcn->assocresp_ies_len = 2968 bcn->assocresp_ies_len =
2940 nla_len(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]); 2969 nla_len(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
2941 } 2970 }
2942 2971
2943 if (info->attrs[NL80211_ATTR_PROBE_RESP]) { 2972 if (attrs[NL80211_ATTR_PROBE_RESP]) {
2944 bcn->probe_resp = 2973 bcn->probe_resp = nla_data(attrs[NL80211_ATTR_PROBE_RESP]);
2945 nla_data(info->attrs[NL80211_ATTR_PROBE_RESP]); 2974 bcn->probe_resp_len = nla_len(attrs[NL80211_ATTR_PROBE_RESP]);
2946 bcn->probe_resp_len =
2947 nla_len(info->attrs[NL80211_ATTR_PROBE_RESP]);
2948 } 2975 }
2949 2976
2950 return 0; 2977 return 0;
@@ -3023,7 +3050,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
3023 !info->attrs[NL80211_ATTR_BEACON_HEAD]) 3050 !info->attrs[NL80211_ATTR_BEACON_HEAD])
3024 return -EINVAL; 3051 return -EINVAL;
3025 3052
3026 err = nl80211_parse_beacon(info, &params.beacon); 3053 err = nl80211_parse_beacon(info->attrs, &params.beacon);
3027 if (err) 3054 if (err)
3028 return err; 3055 return err;
3029 3056
@@ -3175,7 +3202,7 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
3175 if (!wdev->beacon_interval) 3202 if (!wdev->beacon_interval)
3176 return -EINVAL; 3203 return -EINVAL;
3177 3204
3178 err = nl80211_parse_beacon(info, &params); 3205 err = nl80211_parse_beacon(info->attrs, &params);
3179 if (err) 3206 if (err)
3180 return err; 3207 return err;
3181 3208
@@ -6291,11 +6318,16 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
6291 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef)) 6318 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef))
6292 return -EINVAL; 6319 return -EINVAL;
6293 6320
6294 if (ibss.chandef.width > NL80211_CHAN_WIDTH_40) 6321 switch (ibss.chandef.width) {
6295 return -EINVAL; 6322 case NL80211_CHAN_WIDTH_20_NOHT:
6296 if (ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT && 6323 break;
6297 !(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS)) 6324 case NL80211_CHAN_WIDTH_20:
6325 case NL80211_CHAN_WIDTH_40:
6326 if (rdev->wiphy.features & NL80211_FEATURE_HT_IBSS)
6327 break;
6328 default:
6298 return -EINVAL; 6329 return -EINVAL;
6330 }
6299 6331
6300 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; 6332 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
6301 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; 6333 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
@@ -8409,6 +8441,7 @@ static struct genl_ops nl80211_ops[] = {
8409 .cmd = NL80211_CMD_GET_WIPHY, 8441 .cmd = NL80211_CMD_GET_WIPHY,
8410 .doit = nl80211_get_wiphy, 8442 .doit = nl80211_get_wiphy,
8411 .dumpit = nl80211_dump_wiphy, 8443 .dumpit = nl80211_dump_wiphy,
8444 .done = nl80211_dump_wiphy_done,
8412 .policy = nl80211_policy, 8445 .policy = nl80211_policy,
8413 /* can be retrieved by unprivileged users */ 8446 /* can be retrieved by unprivileged users */
8414 .internal_flags = NL80211_FLAG_NEED_WIPHY | 8447 .internal_flags = NL80211_FLAG_NEED_WIPHY |
@@ -9029,13 +9062,13 @@ static struct genl_multicast_group nl80211_regulatory_mcgrp = {
9029void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev) 9062void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
9030{ 9063{
9031 struct sk_buff *msg; 9064 struct sk_buff *msg;
9065 struct nl80211_dump_wiphy_state state = {};
9032 9066
9033 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 9067 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
9034 if (!msg) 9068 if (!msg)
9035 return; 9069 return;
9036 9070
9037 if (nl80211_send_wiphy(rdev, msg, 0, 0, 0, 9071 if (nl80211_send_wiphy(rdev, msg, 0, 0, 0, &state) < 0) {
9038 false, NULL, NULL, NULL) < 0) {
9039 nlmsg_free(msg); 9072 nlmsg_free(msg);
9040 return; 9073 return;
9041 } 9074 }