[NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
.len = 20-1 },
[NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
+
[NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
[NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
+ [NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 },
+ [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },
+ [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },
+
[NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 },
[NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 },
[NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
[NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, },
[NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
[NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
+ [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 },
+ [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 },
};
/* policy for the key attributes */
wdev->iftype == NL80211_IFTYPE_P2P_GO;
}
-static bool nl80211_valid_channel_type(struct genl_info *info,
- enum nl80211_channel_type *channel_type)
+static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
+ struct genl_info *info,
+ struct cfg80211_chan_def *chandef)
{
- enum nl80211_channel_type tmp;
+ u32 control_freq;
- if (!info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE])
- return false;
+ if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
+ return -EINVAL;
- tmp = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
- if (tmp != NL80211_CHAN_NO_HT &&
- tmp != NL80211_CHAN_HT20 &&
- tmp != NL80211_CHAN_HT40PLUS &&
- tmp != NL80211_CHAN_HT40MINUS)
- return false;
+ control_freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
- if (channel_type)
- *channel_type = tmp;
+ chandef->chan = ieee80211_get_channel(&rdev->wiphy, control_freq);
+ chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
+ chandef->center_freq1 = control_freq;
+ chandef->center_freq2 = 0;
- return true;
+ /* Primary channel not allowed */
+ if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED)
+ return -EINVAL;
+
+ if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
+ enum nl80211_channel_type chantype;
+
+ chantype = nla_get_u32(
+ info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
+
+ switch (chantype) {
+ case NL80211_CHAN_NO_HT:
+ case NL80211_CHAN_HT20:
+ case NL80211_CHAN_HT40PLUS:
+ case NL80211_CHAN_HT40MINUS:
+ cfg80211_chandef_create(chandef, chandef->chan,
+ chantype);
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else if (info->attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
+ chandef->width =
+ nla_get_u32(info->attrs[NL80211_ATTR_CHANNEL_WIDTH]);
+ if (info->attrs[NL80211_ATTR_CENTER_FREQ1])
+ chandef->center_freq1 =
+ nla_get_u32(
+ info->attrs[NL80211_ATTR_CENTER_FREQ1]);
+ if (info->attrs[NL80211_ATTR_CENTER_FREQ2])
+ chandef->center_freq2 =
+ nla_get_u32(
+ info->attrs[NL80211_ATTR_CENTER_FREQ2]);
+ }
+
+ if (!cfg80211_chandef_valid(chandef))
+ return -EINVAL;
+
+ if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,
+ IEEE80211_CHAN_DISABLED))
+ return -EINVAL;
+
+ return 0;
}
static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
struct genl_info *info)
{
- struct ieee80211_channel *channel;
- enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
- u32 freq;
+ struct cfg80211_chan_def chandef;
int result;
enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR;
if (wdev)
iftype = wdev->iftype;
- if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
- return -EINVAL;
-
if (!nl80211_can_set_dev_channel(wdev))
return -EOPNOTSUPP;
- if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] &&
- !nl80211_valid_channel_type(info, &channel_type))
- return -EINVAL;
-
- freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
+ result = nl80211_parse_chandef(rdev, info, &chandef);
+ if (result)
+ return result;
mutex_lock(&rdev->devlist_mtx);
switch (iftype) {
result = -EBUSY;
break;
}
- channel = rdev_freq_to_chan(rdev, freq, channel_type);
- if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy,
- channel,
- channel_type)) {
+ if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef)) {
result = -EINVAL;
break;
}
- wdev->preset_chan = channel;
- wdev->preset_chantype = channel_type;
+ wdev->preset_chandef = chandef;
result = 0;
break;
case NL80211_IFTYPE_MESH_POINT:
- result = cfg80211_set_mesh_freq(rdev, wdev, freq, channel_type);
+ result = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
break;
case NL80211_IFTYPE_MONITOR:
- result = cfg80211_set_monitor_channel(rdev, freq, channel_type);
+ result = cfg80211_set_monitor_channel(rdev, &chandef);
break;
default:
result = -EINVAL;
((u64)wiphy_to_dev(wdev->wiphy)->wiphy_idx << 32);
}
+static int nl80211_send_chandef(struct sk_buff *msg,
+ struct cfg80211_chan_def *chandef)
+{
+ WARN_ON(!cfg80211_chandef_valid(chandef));
+
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
+ chandef->chan->center_freq))
+ return -ENOBUFS;
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ case NL80211_CHAN_WIDTH_20:
+ case NL80211_CHAN_WIDTH_40:
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
+ cfg80211_get_chandef_type(chandef)))
+ return -ENOBUFS;
+ break;
+ default:
+ break;
+ }
+ if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width))
+ return -ENOBUFS;
+ if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1))
+ return -ENOBUFS;
+ if (chandef->center_freq2 &&
+ nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2))
+ return -ENOBUFS;
+ return 0;
+}
+
static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev)
goto nla_put_failure;
if (rdev->ops->get_channel) {
- struct ieee80211_channel *chan;
- enum nl80211_channel_type channel_type;
-
- chan = rdev_get_channel(rdev, wdev, &channel_type);
- if (chan &&
- (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
- chan->center_freq) ||
- nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
- channel_type)))
- goto nla_put_failure;
+ int ret;
+ struct cfg80211_chan_def chandef;
+
+ ret = rdev_get_channel(rdev, wdev, &chandef);
+ if (ret == 0) {
+ if (nl80211_send_chandef(msg, &chandef))
+ goto nla_put_failure;
+ }
}
if (wdev->ssid_len) {
wdev->iftype != NL80211_IFTYPE_P2P_GO)
continue;
- if (!wdev->preset_chan)
+ if (!wdev->preset_chandef.chan)
continue;
- params->channel = wdev->preset_chan;
- params->channel_type = wdev->preset_chantype;
+ params->chandef = wdev->preset_chandef;
ret = true;
break;
}
info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
}
- if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
- enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
-
- if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] &&
- !nl80211_valid_channel_type(info, &channel_type))
+ if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
return -EINVAL;
+ params.p2p_ctwindow =
+ nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
+ if (params.p2p_ctwindow > 127)
+ return -EINVAL;
+ if (params.p2p_ctwindow != 0 &&
+ !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
+ return -EINVAL;
+ }
+
+ if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
+ u8 tmp;
- params.channel = rdev_freq_to_chan(rdev,
- nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
- channel_type);
- if (!params.channel)
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
return -EINVAL;
- params.channel_type = channel_type;
- } else if (wdev->preset_chan) {
- params.channel = wdev->preset_chan;
- params.channel_type = wdev->preset_chantype;
+ tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
+ if (tmp > 1)
+ return -EINVAL;
+ params.p2p_opp_ps = tmp;
+ if (params.p2p_opp_ps != 0 &&
+ !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
+ return -EINVAL;
+ }
+
+ if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
+ err = nl80211_parse_chandef(rdev, info, ¶ms.chandef);
+ if (err)
+ return err;
+ } else if (wdev->preset_chandef.chan) {
+ params.chandef = wdev->preset_chandef;
} else if (!nl80211_get_ap_channel(rdev, ¶ms))
return -EINVAL;
- if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, params.channel,
- params.channel_type))
+ if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef))
return -EINVAL;
mutex_lock(&rdev->devlist_mtx);
- err = cfg80211_can_use_chan(rdev, wdev, params.channel,
+ err = cfg80211_can_use_chan(rdev, wdev, params.chandef.chan,
CHAN_MODE_SHARED);
mutex_unlock(&rdev->devlist_mtx);
err = rdev_start_ap(rdev, dev, ¶ms);
if (!err) {
- wdev->preset_chan = params.channel;
- wdev->preset_chantype = params.channel_type;
+ wdev->preset_chandef = params.chandef;
wdev->beacon_interval = params.beacon_interval;
- wdev->channel = params.channel;
+ wdev->channel = params.chandef.chan;
wdev->ssid_len = params.ssid_len;
memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
}
rate = nla_nest_start(msg, attr);
if (!rate)
- goto nla_put_failure;
+ return false;
/* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
bitrate = cfg80211_calculate_bitrate(info);
/* report 16-bit bitrate only if we can */
bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
- if ((bitrate > 0 &&
- nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate)) ||
- (bitrate_compat > 0 &&
- nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat)) ||
- ((info->flags & RATE_INFO_FLAGS_MCS) &&
- nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs)) ||
- ((info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) &&
- nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH)) ||
- ((info->flags & RATE_INFO_FLAGS_SHORT_GI) &&
- nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI)))
- goto nla_put_failure;
+ if (bitrate > 0 &&
+ nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate))
+ return false;
+ if (bitrate_compat > 0 &&
+ nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat))
+ return false;
+
+ if (info->flags & RATE_INFO_FLAGS_MCS) {
+ if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH &&
+ nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
+ nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
+ return false;
+ } else if (info->flags & RATE_INFO_FLAGS_VHT_MCS) {
+ if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_MCS, info->mcs))
+ return false;
+ if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH &&
+ nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH &&
+ nla_put_flag(msg, NL80211_RATE_INFO_80_MHZ_WIDTH))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_80P80_MHZ_WIDTH &&
+ nla_put_flag(msg, NL80211_RATE_INFO_80P80_MHZ_WIDTH))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_160_MHZ_WIDTH &&
+ nla_put_flag(msg, NL80211_RATE_INFO_160_MHZ_WIDTH))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
+ nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
+ return false;
+ }
nla_nest_end(msg, rate);
return true;
-
-nla_put_failure:
- return false;
}
static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
params.use_short_slot_time = -1;
params.ap_isolate = -1;
params.ht_opmode = -1;
+ params.p2p_ctwindow = -1;
+ params.p2p_opp_ps = -1;
if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
params.use_cts_prot =
params.ht_opmode =
nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]);
+ if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ return -EINVAL;
+ params.p2p_ctwindow =
+ nla_get_s8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
+ if (params.p2p_ctwindow < 0)
+ return -EINVAL;
+ if (params.p2p_ctwindow != 0 &&
+ !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
+ return -EINVAL;
+ }
+
+ if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
+ u8 tmp;
+
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ return -EINVAL;
+ tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
+ if (tmp > 1)
+ return -EINVAL;
+ params.p2p_opp_ps = tmp;
+ if (params.p2p_opp_ps &&
+ !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
+ return -EINVAL;
+ }
+
if (!rdev->ops->change_bss)
return -EOPNOTSUPP;
struct cfg80211_internal_bss *intbss)
{
struct cfg80211_bss *res = &intbss->pub;
+ const struct cfg80211_bss_ies *ies;
void *hdr;
struct nlattr *bss;
if (!bss)
goto nla_put_failure;
if ((!is_zero_ether_addr(res->bssid) &&
- nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)) ||
- (res->information_elements && res->len_information_elements &&
- nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
- res->len_information_elements,
- res->information_elements)) ||
- (res->beacon_ies && res->len_beacon_ies &&
- res->beacon_ies != res->information_elements &&
- nla_put(msg, NL80211_BSS_BEACON_IES,
- res->len_beacon_ies, res->beacon_ies)))
+ nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)))
+ goto nla_put_failure;
+
+ rcu_read_lock();
+ ies = rcu_dereference(res->ies);
+ if (ies && ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
+ ies->len, ies->data)) {
+ rcu_read_unlock();
+ goto nla_put_failure;
+ }
+ ies = rcu_dereference(res->beacon_ies);
+ if (ies && ies->len && nla_put(msg, NL80211_BSS_BEACON_IES,
+ ies->len, ies->data)) {
+ rcu_read_unlock();
goto nla_put_failure;
+ }
+ rcu_read_unlock();
+
if (res->tsf &&
nla_put_u64(msg, NL80211_BSS_TSF, res->tsf))
goto nla_put_failure;
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
return -EINVAL;
- if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
- !info->attrs[NL80211_ATTR_SSID] ||
+ if (!info->attrs[NL80211_ATTR_SSID] ||
!nla_len(info->attrs[NL80211_ATTR_SSID]))
return -EINVAL;
ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
}
- if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
- enum nl80211_channel_type channel_type;
-
- if (!nl80211_valid_channel_type(info, &channel_type))
- return -EINVAL;
-
- if (channel_type != NL80211_CHAN_NO_HT &&
- !(wiphy->features & NL80211_FEATURE_HT_IBSS))
- return -EINVAL;
-
- ibss.channel_type = channel_type;
- } else {
- ibss.channel_type = NL80211_CHAN_NO_HT;
- }
+ err = nl80211_parse_chandef(rdev, info, &ibss.chandef);
+ if (err)
+ return err;
- ibss.channel = rdev_freq_to_chan(rdev,
- nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
- ibss.channel_type);
- if (!ibss.channel ||
- ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
- ibss.channel->flags & IEEE80211_CHAN_DISABLED)
+ if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef))
return -EINVAL;
- /* Both channels should be able to initiate communication */
- if ((ibss.channel_type == NL80211_CHAN_HT40PLUS ||
- ibss.channel_type == NL80211_CHAN_HT40MINUS) &&
- !cfg80211_can_beacon_sec_chan(&rdev->wiphy, ibss.channel,
- ibss.channel_type))
+ if (ibss.chandef.width > NL80211_CHAN_WIDTH_40)
+ return -EINVAL;
+ if (ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
+ !(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
return -EINVAL;
ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
int n_rates =
nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
struct ieee80211_supported_band *sband =
- wiphy->bands[ibss.channel->band];
+ wiphy->bands[ibss.chandef.chan->band];
err = ieee80211_get_ratemask(sband, rates, n_rates,
&ibss.basic_rates);
if (IS_ERR(connkeys))
return PTR_ERR(connkeys);
- if ((ibss.channel_type != NL80211_CHAN_NO_HT) && no_ht) {
+ if ((ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) &&
+ no_ht) {
kfree(connkeys);
return -EINVAL;
}
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct wireless_dev *wdev = info->user_ptr[1];
- struct ieee80211_channel *chan;
+ struct cfg80211_chan_def chandef;
struct sk_buff *msg;
void *hdr;
u64 cookie;
- u32 freq, duration;
+ u32 duration;
int err;
if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
duration > rdev->wiphy.max_remain_on_channel_duration)
return -EINVAL;
- if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] &&
- !nl80211_valid_channel_type(info, NULL))
- return -EINVAL;
-
- freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
- chan = rdev_freq_to_chan(rdev, freq, NL80211_CHAN_NO_HT);
- if (chan == NULL)
- return -EINVAL;
+ err = nl80211_parse_chandef(rdev, info, &chandef);
+ if (err)
+ return err;
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg)
goto free_msg;
}
- err = rdev_remain_on_channel(rdev, wdev, chan, duration, &cookie);
+ err = rdev_remain_on_channel(rdev, wdev, chandef.chan,
+ duration, &cookie);
if (err)
goto free_msg;
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct wireless_dev *wdev = info->user_ptr[1];
- struct ieee80211_channel *chan;
- u32 freq;
+ struct cfg80211_chan_def chandef;
int err;
void *hdr = NULL;
u64 cookie;
dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
- if (!info->attrs[NL80211_ATTR_FRAME] ||
- !info->attrs[NL80211_ATTR_WIPHY_FREQ])
+ if (!info->attrs[NL80211_ATTR_FRAME])
return -EINVAL;
if (!rdev->ops->mgmt_tx)
}
- if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] &&
- !nl80211_valid_channel_type(info, NULL))
- return -EINVAL;
-
offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
if (offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
- freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
- chan = rdev_freq_to_chan(rdev, freq, NL80211_CHAN_NO_HT);
- if (chan == NULL)
- return -EINVAL;
+ err = nl80211_parse_chandef(rdev, info, &chandef);
+ if (err)
+ return err;
if (!dont_wait_for_ack) {
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
}
}
- err = cfg80211_mlme_mgmt_tx(rdev, wdev, chan, offchan, wait,
+ err = cfg80211_mlme_mgmt_tx(rdev, wdev, chandef.chan, offchan, wait,
nla_data(info->attrs[NL80211_ATTR_FRAME]),
nla_len(info->attrs[NL80211_ATTR_FRAME]),
no_cck, dont_wait_for_ack, &cookie);
};
static int nl80211_set_cqm_txe(struct genl_info *info,
- u32 rate, u32 pkts, u32 intvl)
+ u32 rate, u32 pkts, u32 intvl)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct wireless_dev *wdev;
struct net_device *dev = info->user_ptr[1];
- if ((rate < 0 || rate > 100) ||
- (intvl < 0 || intvl > NL80211_CQM_TXE_MAX_INTVL))
+ if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL)
return -EINVAL;
wdev = dev->ieee80211_ptr;
}
if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
- enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
-
- if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] &&
- !nl80211_valid_channel_type(info, &channel_type))
- return -EINVAL;
-
- setup.channel = rdev_freq_to_chan(rdev,
- nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
- channel_type);
- if (!setup.channel)
- return -EINVAL;
- setup.channel_type = channel_type;
+ err = nl80211_parse_chandef(rdev, info, &setup.chandef);
+ if (err)
+ return err;
} else {
/* cfg80211_join_mesh() will sort it out */
- setup.channel = NULL;
+ setup.chandef.chan = NULL;
}
return cfg80211_join_mesh(rdev, dev, &setup, &cfg);
}
void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, int freq,
- enum nl80211_channel_type type, gfp_t gfp)
+ struct net_device *netdev,
+ struct cfg80211_chan_def *chandef, gfp_t gfp)
{
struct sk_buff *msg;
void *hdr;
return;
}
- if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
- nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) ||
- nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, type))
+ if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
+ goto nla_put_failure;
+
+ if (nl80211_send_chandef(msg, chandef))
goto nla_put_failure;
genlmsg_end(msg, hdr);