diff options
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 253 |
1 files changed, 127 insertions, 126 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e880f4494950..999108cd947c 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -1381,30 +1381,82 @@ static bool nl80211_valid_channel_type(struct genl_info *info, | |||
1381 | return true; | 1381 | return true; |
1382 | } | 1382 | } |
1383 | 1383 | ||
1384 | static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, | ||
1385 | struct genl_info *info, | ||
1386 | struct cfg80211_chan_def *chandef) | ||
1387 | { | ||
1388 | struct ieee80211_sta_ht_cap *ht_cap; | ||
1389 | struct ieee80211_channel *sc; | ||
1390 | u32 control_freq; | ||
1391 | int offs; | ||
1392 | |||
1393 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) | ||
1394 | return -EINVAL; | ||
1395 | |||
1396 | control_freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | ||
1397 | |||
1398 | chandef->chan = ieee80211_get_channel(&rdev->wiphy, control_freq); | ||
1399 | chandef->_type = NL80211_CHAN_NO_HT; | ||
1400 | |||
1401 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && | ||
1402 | !nl80211_valid_channel_type(info, &chandef->_type)) | ||
1403 | return -EINVAL; | ||
1404 | |||
1405 | /* Primary channel not allowed */ | ||
1406 | if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED) | ||
1407 | return -EINVAL; | ||
1408 | |||
1409 | ht_cap = &rdev->wiphy.bands[chandef->chan->band]->ht_cap; | ||
1410 | |||
1411 | switch (chandef->_type) { | ||
1412 | case NL80211_CHAN_NO_HT: | ||
1413 | break; | ||
1414 | case NL80211_CHAN_HT40MINUS: | ||
1415 | if (chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS) | ||
1416 | return -EINVAL; | ||
1417 | offs = -20; | ||
1418 | /* fall through */ | ||
1419 | case NL80211_CHAN_HT40PLUS: | ||
1420 | if (chandef->_type == NL80211_CHAN_HT40PLUS) { | ||
1421 | if (chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS) | ||
1422 | return -EINVAL; | ||
1423 | offs = 20; | ||
1424 | } | ||
1425 | if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || | ||
1426 | ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT) | ||
1427 | return -EINVAL; | ||
1428 | |||
1429 | sc = ieee80211_get_channel(&rdev->wiphy, | ||
1430 | chandef->chan->center_freq + offs); | ||
1431 | if (!sc || sc->flags & IEEE80211_CHAN_DISABLED) | ||
1432 | return -EINVAL; | ||
1433 | /* fall through */ | ||
1434 | case NL80211_CHAN_HT20: | ||
1435 | if (!ht_cap->ht_supported) | ||
1436 | return -EINVAL; | ||
1437 | break; | ||
1438 | } | ||
1439 | |||
1440 | return 0; | ||
1441 | } | ||
1442 | |||
1384 | static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | 1443 | static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, |
1385 | struct wireless_dev *wdev, | 1444 | struct wireless_dev *wdev, |
1386 | struct genl_info *info) | 1445 | struct genl_info *info) |
1387 | { | 1446 | { |
1388 | struct ieee80211_channel *channel; | 1447 | struct cfg80211_chan_def chandef; |
1389 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | ||
1390 | u32 freq; | ||
1391 | int result; | 1448 | int result; |
1392 | enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR; | 1449 | enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR; |
1393 | 1450 | ||
1394 | if (wdev) | 1451 | if (wdev) |
1395 | iftype = wdev->iftype; | 1452 | iftype = wdev->iftype; |
1396 | 1453 | ||
1397 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) | ||
1398 | return -EINVAL; | ||
1399 | |||
1400 | if (!nl80211_can_set_dev_channel(wdev)) | 1454 | if (!nl80211_can_set_dev_channel(wdev)) |
1401 | return -EOPNOTSUPP; | 1455 | return -EOPNOTSUPP; |
1402 | 1456 | ||
1403 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && | 1457 | result = nl80211_parse_chandef(rdev, info, &chandef); |
1404 | !nl80211_valid_channel_type(info, &channel_type)) | 1458 | if (result) |
1405 | return -EINVAL; | 1459 | return result; |
1406 | |||
1407 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | ||
1408 | 1460 | ||
1409 | mutex_lock(&rdev->devlist_mtx); | 1461 | mutex_lock(&rdev->devlist_mtx); |
1410 | switch (iftype) { | 1462 | switch (iftype) { |
@@ -1414,22 +1466,18 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | |||
1414 | result = -EBUSY; | 1466 | result = -EBUSY; |
1415 | break; | 1467 | break; |
1416 | } | 1468 | } |
1417 | channel = rdev_freq_to_chan(rdev, freq, channel_type); | 1469 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef)) { |
1418 | if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy, | ||
1419 | channel, | ||
1420 | channel_type)) { | ||
1421 | result = -EINVAL; | 1470 | result = -EINVAL; |
1422 | break; | 1471 | break; |
1423 | } | 1472 | } |
1424 | wdev->preset_chan = channel; | 1473 | wdev->preset_chandef = chandef; |
1425 | wdev->preset_chantype = channel_type; | ||
1426 | result = 0; | 1474 | result = 0; |
1427 | break; | 1475 | break; |
1428 | case NL80211_IFTYPE_MESH_POINT: | 1476 | case NL80211_IFTYPE_MESH_POINT: |
1429 | result = cfg80211_set_mesh_freq(rdev, wdev, freq, channel_type); | 1477 | result = cfg80211_set_mesh_channel(rdev, wdev, &chandef); |
1430 | break; | 1478 | break; |
1431 | case NL80211_IFTYPE_MONITOR: | 1479 | case NL80211_IFTYPE_MONITOR: |
1432 | result = cfg80211_set_monitor_channel(rdev, freq, channel_type); | 1480 | result = cfg80211_set_monitor_channel(rdev, &chandef); |
1433 | break; | 1481 | break; |
1434 | default: | 1482 | default: |
1435 | result = -EINVAL; | 1483 | result = -EINVAL; |
@@ -1749,6 +1797,17 @@ static inline u64 wdev_id(struct wireless_dev *wdev) | |||
1749 | ((u64)wiphy_to_dev(wdev->wiphy)->wiphy_idx << 32); | 1797 | ((u64)wiphy_to_dev(wdev->wiphy)->wiphy_idx << 32); |
1750 | } | 1798 | } |
1751 | 1799 | ||
1800 | static int nl80211_send_chandef(struct sk_buff *msg, | ||
1801 | struct cfg80211_chan_def *chandef) | ||
1802 | { | ||
1803 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, | ||
1804 | chandef->chan->center_freq)) | ||
1805 | return -ENOBUFS; | ||
1806 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, chandef->_type)) | ||
1807 | return -ENOBUFS; | ||
1808 | return 0; | ||
1809 | } | ||
1810 | |||
1752 | static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, | 1811 | static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, |
1753 | struct cfg80211_registered_device *rdev, | 1812 | struct cfg80211_registered_device *rdev, |
1754 | struct wireless_dev *wdev) | 1813 | struct wireless_dev *wdev) |
@@ -1775,16 +1834,14 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag | |||
1775 | goto nla_put_failure; | 1834 | goto nla_put_failure; |
1776 | 1835 | ||
1777 | if (rdev->ops->get_channel) { | 1836 | if (rdev->ops->get_channel) { |
1778 | struct ieee80211_channel *chan; | 1837 | int ret; |
1779 | enum nl80211_channel_type channel_type; | 1838 | struct cfg80211_chan_def chandef; |
1780 | 1839 | ||
1781 | chan = rdev_get_channel(rdev, wdev, &channel_type); | 1840 | ret = rdev_get_channel(rdev, wdev, &chandef); |
1782 | if (chan && | 1841 | if (ret == 0) { |
1783 | (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, | 1842 | if (nl80211_send_chandef(msg, &chandef)) |
1784 | chan->center_freq) || | 1843 | goto nla_put_failure; |
1785 | nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, | 1844 | } |
1786 | channel_type))) | ||
1787 | goto nla_put_failure; | ||
1788 | } | 1845 | } |
1789 | 1846 | ||
1790 | if (wdev->ssid_len) { | 1847 | if (wdev->ssid_len) { |
@@ -2492,11 +2549,10 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev, | |||
2492 | wdev->iftype != NL80211_IFTYPE_P2P_GO) | 2549 | wdev->iftype != NL80211_IFTYPE_P2P_GO) |
2493 | continue; | 2550 | continue; |
2494 | 2551 | ||
2495 | if (!wdev->preset_chan) | 2552 | if (!wdev->preset_chandef.chan) |
2496 | continue; | 2553 | continue; |
2497 | 2554 | ||
2498 | params->channel = wdev->preset_chan; | 2555 | params->chandef = wdev->preset_chandef; |
2499 | params->channel_type = wdev->preset_chantype; | ||
2500 | ret = true; | 2556 | ret = true; |
2501 | break; | 2557 | break; |
2502 | } | 2558 | } |
@@ -2618,30 +2674,19 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
2618 | } | 2674 | } |
2619 | 2675 | ||
2620 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 2676 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { |
2621 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | 2677 | err = nl80211_parse_chandef(rdev, info, ¶ms.chandef); |
2622 | 2678 | if (err) | |
2623 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && | 2679 | return err; |
2624 | !nl80211_valid_channel_type(info, &channel_type)) | 2680 | } else if (wdev->preset_chandef.chan) { |
2625 | return -EINVAL; | 2681 | params.chandef = wdev->preset_chandef; |
2626 | |||
2627 | params.channel = rdev_freq_to_chan(rdev, | ||
2628 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]), | ||
2629 | channel_type); | ||
2630 | if (!params.channel) | ||
2631 | return -EINVAL; | ||
2632 | params.channel_type = channel_type; | ||
2633 | } else if (wdev->preset_chan) { | ||
2634 | params.channel = wdev->preset_chan; | ||
2635 | params.channel_type = wdev->preset_chantype; | ||
2636 | } else if (!nl80211_get_ap_channel(rdev, ¶ms)) | 2682 | } else if (!nl80211_get_ap_channel(rdev, ¶ms)) |
2637 | return -EINVAL; | 2683 | return -EINVAL; |
2638 | 2684 | ||
2639 | if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, params.channel, | 2685 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef)) |
2640 | params.channel_type)) | ||
2641 | return -EINVAL; | 2686 | return -EINVAL; |
2642 | 2687 | ||
2643 | mutex_lock(&rdev->devlist_mtx); | 2688 | mutex_lock(&rdev->devlist_mtx); |
2644 | err = cfg80211_can_use_chan(rdev, wdev, params.channel, | 2689 | err = cfg80211_can_use_chan(rdev, wdev, params.chandef.chan, |
2645 | CHAN_MODE_SHARED); | 2690 | CHAN_MODE_SHARED); |
2646 | mutex_unlock(&rdev->devlist_mtx); | 2691 | mutex_unlock(&rdev->devlist_mtx); |
2647 | 2692 | ||
@@ -2650,10 +2695,9 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
2650 | 2695 | ||
2651 | err = rdev_start_ap(rdev, dev, ¶ms); | 2696 | err = rdev_start_ap(rdev, dev, ¶ms); |
2652 | if (!err) { | 2697 | if (!err) { |
2653 | wdev->preset_chan = params.channel; | 2698 | wdev->preset_chandef = params.chandef; |
2654 | wdev->preset_chantype = params.channel_type; | ||
2655 | wdev->beacon_interval = params.beacon_interval; | 2699 | wdev->beacon_interval = params.beacon_interval; |
2656 | wdev->channel = params.channel; | 2700 | wdev->channel = params.chandef.chan; |
2657 | wdev->ssid_len = params.ssid_len; | 2701 | wdev->ssid_len = params.ssid_len; |
2658 | memcpy(wdev->ssid, params.ssid, wdev->ssid_len); | 2702 | memcpy(wdev->ssid, params.ssid, wdev->ssid_len); |
2659 | } | 2703 | } |
@@ -5330,8 +5374,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
5330 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 5374 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
5331 | return -EINVAL; | 5375 | return -EINVAL; |
5332 | 5376 | ||
5333 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] || | 5377 | if (!info->attrs[NL80211_ATTR_SSID] || |
5334 | !info->attrs[NL80211_ATTR_SSID] || | ||
5335 | !nla_len(info->attrs[NL80211_ATTR_SSID])) | 5378 | !nla_len(info->attrs[NL80211_ATTR_SSID])) |
5336 | return -EINVAL; | 5379 | return -EINVAL; |
5337 | 5380 | ||
@@ -5366,34 +5409,11 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
5366 | ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 5409 | ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
5367 | } | 5410 | } |
5368 | 5411 | ||
5369 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { | 5412 | err = nl80211_parse_chandef(rdev, info, &ibss.chandef); |
5370 | enum nl80211_channel_type channel_type; | 5413 | if (err) |
5371 | 5414 | return err; | |
5372 | if (!nl80211_valid_channel_type(info, &channel_type)) | ||
5373 | return -EINVAL; | ||
5374 | |||
5375 | if (channel_type != NL80211_CHAN_NO_HT && | ||
5376 | !(wiphy->features & NL80211_FEATURE_HT_IBSS)) | ||
5377 | return -EINVAL; | ||
5378 | |||
5379 | ibss.channel_type = channel_type; | ||
5380 | } else { | ||
5381 | ibss.channel_type = NL80211_CHAN_NO_HT; | ||
5382 | } | ||
5383 | |||
5384 | ibss.channel = rdev_freq_to_chan(rdev, | ||
5385 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]), | ||
5386 | ibss.channel_type); | ||
5387 | if (!ibss.channel || | ||
5388 | ibss.channel->flags & IEEE80211_CHAN_NO_IBSS || | ||
5389 | ibss.channel->flags & IEEE80211_CHAN_DISABLED) | ||
5390 | return -EINVAL; | ||
5391 | 5415 | ||
5392 | /* Both channels should be able to initiate communication */ | 5416 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef)) |
5393 | if ((ibss.channel_type == NL80211_CHAN_HT40PLUS || | ||
5394 | ibss.channel_type == NL80211_CHAN_HT40MINUS) && | ||
5395 | !cfg80211_can_beacon_sec_chan(&rdev->wiphy, ibss.channel, | ||
5396 | ibss.channel_type)) | ||
5397 | return -EINVAL; | 5417 | return -EINVAL; |
5398 | 5418 | ||
5399 | ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; | 5419 | ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; |
@@ -5405,7 +5425,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
5405 | int n_rates = | 5425 | int n_rates = |
5406 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); | 5426 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); |
5407 | struct ieee80211_supported_band *sband = | 5427 | struct ieee80211_supported_band *sband = |
5408 | wiphy->bands[ibss.channel->band]; | 5428 | wiphy->bands[ibss.chandef.chan->band]; |
5409 | 5429 | ||
5410 | err = ieee80211_get_ratemask(sband, rates, n_rates, | 5430 | err = ieee80211_get_ratemask(sband, rates, n_rates, |
5411 | &ibss.basic_rates); | 5431 | &ibss.basic_rates); |
@@ -5427,7 +5447,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
5427 | if (IS_ERR(connkeys)) | 5447 | if (IS_ERR(connkeys)) |
5428 | return PTR_ERR(connkeys); | 5448 | return PTR_ERR(connkeys); |
5429 | 5449 | ||
5430 | if ((ibss.channel_type != NL80211_CHAN_NO_HT) && no_ht) { | 5450 | if ((ibss.chandef._type != NL80211_CHAN_NO_HT) && no_ht) { |
5431 | kfree(connkeys); | 5451 | kfree(connkeys); |
5432 | return -EINVAL; | 5452 | return -EINVAL; |
5433 | } | 5453 | } |
@@ -5948,11 +5968,11 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, | |||
5948 | { | 5968 | { |
5949 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 5969 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
5950 | struct wireless_dev *wdev = info->user_ptr[1]; | 5970 | struct wireless_dev *wdev = info->user_ptr[1]; |
5951 | struct ieee80211_channel *chan; | 5971 | struct cfg80211_chan_def chandef; |
5952 | struct sk_buff *msg; | 5972 | struct sk_buff *msg; |
5953 | void *hdr; | 5973 | void *hdr; |
5954 | u64 cookie; | 5974 | u64 cookie; |
5955 | u32 freq, duration; | 5975 | u32 duration; |
5956 | int err; | 5976 | int err; |
5957 | 5977 | ||
5958 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] || | 5978 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] || |
@@ -5973,14 +5993,9 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, | |||
5973 | duration > rdev->wiphy.max_remain_on_channel_duration) | 5993 | duration > rdev->wiphy.max_remain_on_channel_duration) |
5974 | return -EINVAL; | 5994 | return -EINVAL; |
5975 | 5995 | ||
5976 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && | 5996 | err = nl80211_parse_chandef(rdev, info, &chandef); |
5977 | !nl80211_valid_channel_type(info, NULL)) | 5997 | if (err) |
5978 | return -EINVAL; | 5998 | return err; |
5979 | |||
5980 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | ||
5981 | chan = rdev_freq_to_chan(rdev, freq, NL80211_CHAN_NO_HT); | ||
5982 | if (chan == NULL) | ||
5983 | return -EINVAL; | ||
5984 | 5999 | ||
5985 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 6000 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
5986 | if (!msg) | 6001 | if (!msg) |
@@ -5994,7 +6009,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, | |||
5994 | goto free_msg; | 6009 | goto free_msg; |
5995 | } | 6010 | } |
5996 | 6011 | ||
5997 | err = rdev_remain_on_channel(rdev, wdev, chan, duration, &cookie); | 6012 | err = rdev_remain_on_channel(rdev, wdev, chandef.chan, |
6013 | duration, &cookie); | ||
5998 | 6014 | ||
5999 | if (err) | 6015 | if (err) |
6000 | goto free_msg; | 6016 | goto free_msg; |
@@ -6213,8 +6229,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
6213 | { | 6229 | { |
6214 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 6230 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
6215 | struct wireless_dev *wdev = info->user_ptr[1]; | 6231 | struct wireless_dev *wdev = info->user_ptr[1]; |
6216 | struct ieee80211_channel *chan; | 6232 | struct cfg80211_chan_def chandef; |
6217 | u32 freq; | ||
6218 | int err; | 6233 | int err; |
6219 | void *hdr = NULL; | 6234 | void *hdr = NULL; |
6220 | u64 cookie; | 6235 | u64 cookie; |
@@ -6224,8 +6239,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
6224 | 6239 | ||
6225 | dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK]; | 6240 | dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK]; |
6226 | 6241 | ||
6227 | if (!info->attrs[NL80211_ATTR_FRAME] || | 6242 | if (!info->attrs[NL80211_ATTR_FRAME]) |
6228 | !info->attrs[NL80211_ATTR_WIPHY_FREQ]) | ||
6229 | return -EINVAL; | 6243 | return -EINVAL; |
6230 | 6244 | ||
6231 | if (!rdev->ops->mgmt_tx) | 6245 | if (!rdev->ops->mgmt_tx) |
@@ -6260,10 +6274,6 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
6260 | 6274 | ||
6261 | } | 6275 | } |
6262 | 6276 | ||
6263 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && | ||
6264 | !nl80211_valid_channel_type(info, NULL)) | ||
6265 | return -EINVAL; | ||
6266 | |||
6267 | offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK]; | 6277 | offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK]; |
6268 | 6278 | ||
6269 | if (offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) | 6279 | if (offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) |
@@ -6271,10 +6281,9 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
6271 | 6281 | ||
6272 | no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); | 6282 | no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); |
6273 | 6283 | ||
6274 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | 6284 | err = nl80211_parse_chandef(rdev, info, &chandef); |
6275 | chan = rdev_freq_to_chan(rdev, freq, NL80211_CHAN_NO_HT); | 6285 | if (err) |
6276 | if (chan == NULL) | 6286 | return err; |
6277 | return -EINVAL; | ||
6278 | 6287 | ||
6279 | if (!dont_wait_for_ack) { | 6288 | if (!dont_wait_for_ack) { |
6280 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 6289 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
@@ -6290,7 +6299,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
6290 | } | 6299 | } |
6291 | } | 6300 | } |
6292 | 6301 | ||
6293 | err = cfg80211_mlme_mgmt_tx(rdev, wdev, chan, offchan, wait, | 6302 | err = cfg80211_mlme_mgmt_tx(rdev, wdev, chandef.chan, offchan, wait, |
6294 | nla_data(info->attrs[NL80211_ATTR_FRAME]), | 6303 | nla_data(info->attrs[NL80211_ATTR_FRAME]), |
6295 | nla_len(info->attrs[NL80211_ATTR_FRAME]), | 6304 | nla_len(info->attrs[NL80211_ATTR_FRAME]), |
6296 | no_cck, dont_wait_for_ack, &cookie); | 6305 | no_cck, dont_wait_for_ack, &cookie); |
@@ -6554,21 +6563,12 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | |||
6554 | } | 6563 | } |
6555 | 6564 | ||
6556 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 6565 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { |
6557 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | 6566 | err = nl80211_parse_chandef(rdev, info, &setup.chandef); |
6558 | 6567 | if (err) | |
6559 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && | 6568 | return err; |
6560 | !nl80211_valid_channel_type(info, &channel_type)) | ||
6561 | return -EINVAL; | ||
6562 | |||
6563 | setup.channel = rdev_freq_to_chan(rdev, | ||
6564 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]), | ||
6565 | channel_type); | ||
6566 | if (!setup.channel) | ||
6567 | return -EINVAL; | ||
6568 | setup.channel_type = channel_type; | ||
6569 | } else { | 6569 | } else { |
6570 | /* cfg80211_join_mesh() will sort it out */ | 6570 | /* cfg80211_join_mesh() will sort it out */ |
6571 | setup.channel = NULL; | 6571 | setup.chandef.chan = NULL; |
6572 | } | 6572 | } |
6573 | 6573 | ||
6574 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); | 6574 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); |
@@ -8800,8 +8800,8 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, | |||
8800 | } | 8800 | } |
8801 | 8801 | ||
8802 | void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, | 8802 | void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, |
8803 | struct net_device *netdev, int freq, | 8803 | struct net_device *netdev, |
8804 | enum nl80211_channel_type type, gfp_t gfp) | 8804 | struct cfg80211_chan_def *chandef, gfp_t gfp) |
8805 | { | 8805 | { |
8806 | struct sk_buff *msg; | 8806 | struct sk_buff *msg; |
8807 | void *hdr; | 8807 | void *hdr; |
@@ -8816,9 +8816,10 @@ void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, | |||
8816 | return; | 8816 | return; |
8817 | } | 8817 | } |
8818 | 8818 | ||
8819 | if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 8819 | if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) |
8820 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) || | 8820 | goto nla_put_failure; |
8821 | nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, type)) | 8821 | |
8822 | if (nl80211_send_chandef(msg, chandef)) | ||
8822 | goto nla_put_failure; | 8823 | goto nla_put_failure; |
8823 | 8824 | ||
8824 | genlmsg_end(msg, hdr); | 8825 | genlmsg_end(msg, hdr); |