aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c155
1 files changed, 82 insertions, 73 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d038fa45ecd1..f45706adaf34 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -363,6 +363,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
363 [NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, }, 363 [NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, },
364 [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN }, 364 [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
365 [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 }, 365 [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
366 [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 },
367 [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 },
366}; 368};
367 369
368/* policy for the key attributes */ 370/* policy for the key attributes */
@@ -1369,9 +1371,7 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
1369 struct genl_info *info, 1371 struct genl_info *info,
1370 struct cfg80211_chan_def *chandef) 1372 struct cfg80211_chan_def *chandef)
1371{ 1373{
1372 struct ieee80211_sta_ht_cap *ht_cap; 1374 u32 control_freq;
1373 struct ieee80211_sta_vht_cap *vht_cap;
1374 u32 control_freq, width;
1375 1375
1376 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) 1376 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
1377 return -EINVAL; 1377 return -EINVAL;
@@ -1417,67 +1417,13 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
1417 info->attrs[NL80211_ATTR_CENTER_FREQ2]); 1417 info->attrs[NL80211_ATTR_CENTER_FREQ2]);
1418 } 1418 }
1419 1419
1420 ht_cap = &rdev->wiphy.bands[chandef->chan->band]->ht_cap; 1420 if (!cfg80211_chandef_valid(chandef))
1421 vht_cap = &rdev->wiphy.bands[chandef->chan->band]->vht_cap;
1422
1423 if (!cfg80211_chan_def_valid(chandef))
1424 return -EINVAL; 1421 return -EINVAL;
1425 1422
1426 switch (chandef->width) { 1423 if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,
1427 case NL80211_CHAN_WIDTH_20: 1424 IEEE80211_CHAN_DISABLED))
1428 if (!ht_cap->ht_supported)
1429 return -EINVAL;
1430 case NL80211_CHAN_WIDTH_20_NOHT:
1431 width = 20;
1432 break;
1433 case NL80211_CHAN_WIDTH_40:
1434 width = 40;
1435 /* quick early regulatory check */
1436 if (chandef->center_freq1 < control_freq &&
1437 chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
1438 return -EINVAL;
1439 if (chandef->center_freq1 > control_freq &&
1440 chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
1441 return -EINVAL;
1442 if (!ht_cap->ht_supported)
1443 return -EINVAL;
1444 if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
1445 ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
1446 return -EINVAL;
1447 break;
1448 case NL80211_CHAN_WIDTH_80:
1449 width = 80;
1450 if (!vht_cap->vht_supported)
1451 return -EINVAL;
1452 break;
1453 case NL80211_CHAN_WIDTH_80P80:
1454 width = 80;
1455 if (!vht_cap->vht_supported)
1456 return -EINVAL;
1457 if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))
1458 return -EINVAL;
1459 break;
1460 case NL80211_CHAN_WIDTH_160:
1461 width = 160;
1462 if (!vht_cap->vht_supported)
1463 return -EINVAL;
1464 if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ))
1465 return -EINVAL;
1466 break;
1467 default:
1468 return -EINVAL;
1469 }
1470
1471 if (!cfg80211_secondary_chans_ok(&rdev->wiphy, chandef->center_freq1,
1472 width, IEEE80211_CHAN_DISABLED))
1473 return -EINVAL;
1474 if (chandef->center_freq2 &&
1475 !cfg80211_secondary_chans_ok(&rdev->wiphy, chandef->center_freq2,
1476 width, IEEE80211_CHAN_DISABLED))
1477 return -EINVAL; 1425 return -EINVAL;
1478 1426
1479 /* TODO: missing regulatory check on bandwidth */
1480
1481 return 0; 1427 return 0;
1482} 1428}
1483 1429
@@ -1841,7 +1787,7 @@ static inline u64 wdev_id(struct wireless_dev *wdev)
1841static int nl80211_send_chandef(struct sk_buff *msg, 1787static int nl80211_send_chandef(struct sk_buff *msg,
1842 struct cfg80211_chan_def *chandef) 1788 struct cfg80211_chan_def *chandef)
1843{ 1789{
1844 WARN_ON(!cfg80211_chan_def_valid(chandef)); 1790 WARN_ON(!cfg80211_chandef_valid(chandef));
1845 1791
1846 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, 1792 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
1847 chandef->chan->center_freq)) 1793 chandef->chan->center_freq))
@@ -2732,6 +2678,32 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
2732 info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]); 2678 info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
2733 } 2679 }
2734 2680
2681 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
2682 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
2683 return -EINVAL;
2684 params.p2p_ctwindow =
2685 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
2686 if (params.p2p_ctwindow > 127)
2687 return -EINVAL;
2688 if (params.p2p_ctwindow != 0 &&
2689 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
2690 return -EINVAL;
2691 }
2692
2693 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
2694 u8 tmp;
2695
2696 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
2697 return -EINVAL;
2698 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
2699 if (tmp > 1)
2700 return -EINVAL;
2701 params.p2p_opp_ps = tmp;
2702 if (params.p2p_opp_ps != 0 &&
2703 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
2704 return -EINVAL;
2705 }
2706
2735 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { 2707 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
2736 err = nl80211_parse_chandef(rdev, info, &params.chandef); 2708 err = nl80211_parse_chandef(rdev, info, &params.chandef);
2737 if (err) 2709 if (err)
@@ -3698,6 +3670,8 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
3698 params.use_short_slot_time = -1; 3670 params.use_short_slot_time = -1;
3699 params.ap_isolate = -1; 3671 params.ap_isolate = -1;
3700 params.ht_opmode = -1; 3672 params.ht_opmode = -1;
3673 params.p2p_ctwindow = -1;
3674 params.p2p_opp_ps = -1;
3701 3675
3702 if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) 3676 if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
3703 params.use_cts_prot = 3677 params.use_cts_prot =
@@ -3720,6 +3694,32 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
3720 params.ht_opmode = 3694 params.ht_opmode =
3721 nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]); 3695 nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]);
3722 3696
3697 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
3698 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
3699 return -EINVAL;
3700 params.p2p_ctwindow =
3701 nla_get_s8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
3702 if (params.p2p_ctwindow < 0)
3703 return -EINVAL;
3704 if (params.p2p_ctwindow != 0 &&
3705 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
3706 return -EINVAL;
3707 }
3708
3709 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
3710 u8 tmp;
3711
3712 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
3713 return -EINVAL;
3714 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
3715 if (tmp > 1)
3716 return -EINVAL;
3717 params.p2p_opp_ps = tmp;
3718 if (params.p2p_opp_ps &&
3719 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
3720 return -EINVAL;
3721 }
3722
3723 if (!rdev->ops->change_bss) 3723 if (!rdev->ops->change_bss)
3724 return -EOPNOTSUPP; 3724 return -EOPNOTSUPP;
3725 3725
@@ -4808,6 +4808,7 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
4808 struct cfg80211_internal_bss *intbss) 4808 struct cfg80211_internal_bss *intbss)
4809{ 4809{
4810 struct cfg80211_bss *res = &intbss->pub; 4810 struct cfg80211_bss *res = &intbss->pub;
4811 const struct cfg80211_bss_ies *ies;
4811 void *hdr; 4812 void *hdr;
4812 struct nlattr *bss; 4813 struct nlattr *bss;
4813 4814
@@ -4828,16 +4829,24 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
4828 if (!bss) 4829 if (!bss)
4829 goto nla_put_failure; 4830 goto nla_put_failure;
4830 if ((!is_zero_ether_addr(res->bssid) && 4831 if ((!is_zero_ether_addr(res->bssid) &&
4831 nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)) || 4832 nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)))
4832 (res->information_elements && res->len_information_elements && 4833 goto nla_put_failure;
4833 nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS, 4834
4834 res->len_information_elements, 4835 rcu_read_lock();
4835 res->information_elements)) || 4836 ies = rcu_dereference(res->ies);
4836 (res->beacon_ies && res->len_beacon_ies && 4837 if (ies && ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
4837 res->beacon_ies != res->information_elements && 4838 ies->len, ies->data)) {
4838 nla_put(msg, NL80211_BSS_BEACON_IES, 4839 rcu_read_unlock();
4839 res->len_beacon_ies, res->beacon_ies))) 4840 goto nla_put_failure;
4841 }
4842 ies = rcu_dereference(res->beacon_ies);
4843 if (ies && ies->len && nla_put(msg, NL80211_BSS_BEACON_IES,
4844 ies->len, ies->data)) {
4845 rcu_read_unlock();
4840 goto nla_put_failure; 4846 goto nla_put_failure;
4847 }
4848 rcu_read_unlock();
4849
4841 if (res->tsf && 4850 if (res->tsf &&
4842 nla_put_u64(msg, NL80211_BSS_TSF, res->tsf)) 4851 nla_put_u64(msg, NL80211_BSS_TSF, res->tsf))
4843 goto nla_put_failure; 4852 goto nla_put_failure;
@@ -5502,6 +5511,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
5502 return -EINVAL; 5511 return -EINVAL;
5503 if (ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT && 5512 if (ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
5504 !(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS)) 5513 !(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
5514 return -EINVAL;
5505 5515
5506 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; 5516 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
5507 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; 5517 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
@@ -6529,14 +6539,13 @@ nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] __read_mostly = {
6529}; 6539};
6530 6540
6531static int nl80211_set_cqm_txe(struct genl_info *info, 6541static int nl80211_set_cqm_txe(struct genl_info *info,
6532 u32 rate, u32 pkts, u32 intvl) 6542 u32 rate, u32 pkts, u32 intvl)
6533{ 6543{
6534 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 6544 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6535 struct wireless_dev *wdev; 6545 struct wireless_dev *wdev;
6536 struct net_device *dev = info->user_ptr[1]; 6546 struct net_device *dev = info->user_ptr[1];
6537 6547
6538 if ((rate < 0 || rate > 100) || 6548 if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL)
6539 (intvl < 0 || intvl > NL80211_CQM_TXE_MAX_INTVL))
6540 return -EINVAL; 6549 return -EINVAL;
6541 6550
6542 wdev = dev->ieee80211_ptr; 6551 wdev = dev->ieee80211_ptr;