Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Conflicts: net/wireless/reg.c
This commit is contained in:
commit
353c78152c
38 changed files with 1302 additions and 453 deletions
|
@ -504,7 +504,8 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
|
|||
case NL80211_IFTYPE_ADHOC:
|
||||
if (wdev->current_bss) {
|
||||
*chan = wdev->current_bss->pub.channel;
|
||||
*chanmode = wdev->ibss_fixed
|
||||
*chanmode = (wdev->ibss_fixed &&
|
||||
!wdev->ibss_dfs_possible)
|
||||
? CHAN_MODE_SHARED
|
||||
: CHAN_MODE_EXCLUSIVE;
|
||||
return;
|
||||
|
|
|
@ -83,6 +83,8 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
|
|||
struct cfg80211_cached_keys *connkeys)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct ieee80211_channel *check_chan;
|
||||
u8 radar_detect_width = 0;
|
||||
int err;
|
||||
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
@ -114,14 +116,28 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
|
|||
wdev->connect_keys = connkeys;
|
||||
|
||||
wdev->ibss_fixed = params->channel_fixed;
|
||||
wdev->ibss_dfs_possible = params->userspace_handles_dfs;
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
wdev->wext.ibss.chandef = params->chandef;
|
||||
#endif
|
||||
check_chan = params->chandef.chan;
|
||||
if (params->userspace_handles_dfs) {
|
||||
/* use channel NULL to check for radar even if the current
|
||||
* channel is not a radar channel - it might decide to change
|
||||
* to DFS channel later.
|
||||
*/
|
||||
radar_detect_width = BIT(params->chandef.width);
|
||||
check_chan = NULL;
|
||||
}
|
||||
|
||||
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
|
||||
check_chan,
|
||||
(params->channel_fixed &&
|
||||
!radar_detect_width)
|
||||
? CHAN_MODE_SHARED
|
||||
: CHAN_MODE_EXCLUSIVE,
|
||||
radar_detect_width);
|
||||
|
||||
err = cfg80211_can_use_chan(rdev, wdev, params->chandef.chan,
|
||||
params->channel_fixed
|
||||
? CHAN_MODE_SHARED
|
||||
: CHAN_MODE_EXCLUSIVE);
|
||||
if (err) {
|
||||
wdev->connect_keys = NULL;
|
||||
return err;
|
||||
|
|
|
@ -354,6 +354,9 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
|
|||
[NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
|
||||
[NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 },
|
||||
[NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 },
|
||||
[NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY },
|
||||
[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
|
||||
[NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
|
@ -3896,9 +3899,45 @@ static int nl80211_parse_sta_wme(struct genl_info *info,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_parse_sta_channel_info(struct genl_info *info,
|
||||
struct station_parameters *params)
|
||||
{
|
||||
if (info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]) {
|
||||
params->supported_channels =
|
||||
nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
|
||||
params->supported_channels_len =
|
||||
nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
|
||||
/*
|
||||
* Need to include at least one (first channel, number of
|
||||
* channels) tuple for each subband, and must have proper
|
||||
* tuples for the rest of the data as well.
|
||||
*/
|
||||
if (params->supported_channels_len < 2)
|
||||
return -EINVAL;
|
||||
if (params->supported_channels_len % 2)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]) {
|
||||
params->supported_oper_classes =
|
||||
nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
|
||||
params->supported_oper_classes_len =
|
||||
nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
|
||||
/*
|
||||
* The value of the Length field of the Supported Operating
|
||||
* Classes element is between 2 and 253.
|
||||
*/
|
||||
if (params->supported_oper_classes_len < 2 ||
|
||||
params->supported_oper_classes_len > 253)
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_set_station_tdls(struct genl_info *info,
|
||||
struct station_parameters *params)
|
||||
{
|
||||
int err;
|
||||
/* Dummy STA entry gets updated once the peer capabilities are known */
|
||||
if (info->attrs[NL80211_ATTR_PEER_AID])
|
||||
params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
|
||||
|
@ -3909,6 +3948,10 @@ static int nl80211_set_station_tdls(struct genl_info *info,
|
|||
params->vht_capa =
|
||||
nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
|
||||
|
||||
err = nl80211_parse_sta_channel_info(info, params);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return nl80211_parse_sta_wme(info, params);
|
||||
}
|
||||
|
||||
|
@ -4089,6 +4132,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = nl80211_parse_sta_channel_info(info, ¶ms);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = nl80211_parse_sta_wme(info, ¶ms);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -5653,6 +5700,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
|
|||
return -EINVAL;
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -5665,9 +5713,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
|
|||
return -EINVAL;
|
||||
|
||||
/* only important for AP, IBSS and mesh create IEs internally */
|
||||
if (need_new_beacon &&
|
||||
(!info->attrs[NL80211_ATTR_CSA_IES] ||
|
||||
!info->attrs[NL80211_ATTR_CSA_C_OFF_BEACON]))
|
||||
if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES])
|
||||
return -EINVAL;
|
||||
|
||||
params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
|
||||
|
@ -5722,9 +5768,9 @@ skip_beacons:
|
|||
if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef))
|
||||
return -EINVAL;
|
||||
|
||||
/* DFS channels are only supported for AP/P2P GO ... for now. */
|
||||
if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP ||
|
||||
dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
|
||||
dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO ||
|
||||
dev->ieee80211_ptr->iftype == NL80211_IFTYPE_ADHOC) {
|
||||
err = cfg80211_chandef_dfs_required(wdev->wiphy,
|
||||
¶ms.chandef);
|
||||
if (err < 0) {
|
||||
|
@ -6556,6 +6602,9 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
|
|||
ibss.control_port =
|
||||
nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]);
|
||||
|
||||
ibss.userspace_handles_dfs =
|
||||
nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
|
||||
|
||||
err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
|
||||
if (err)
|
||||
kfree(connkeys);
|
||||
|
@ -10762,7 +10811,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
|
|||
|
||||
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
|
||||
wdev->iftype != NL80211_IFTYPE_P2P_GO &&
|
||||
wdev->iftype != NL80211_IFTYPE_ADHOC))
|
||||
wdev->iftype != NL80211_IFTYPE_ADHOC &&
|
||||
wdev->iftype != NL80211_IFTYPE_MESH_POINT))
|
||||
goto out;
|
||||
|
||||
wdev->channel = chandef->chan;
|
||||
|
|
|
@ -787,7 +787,6 @@ const char *reg_initiator_name(enum nl80211_reg_initiator initiator)
|
|||
EXPORT_SYMBOL(reg_initiator_name);
|
||||
|
||||
#ifdef CONFIG_CFG80211_REG_DEBUG
|
||||
|
||||
static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan,
|
||||
const struct ieee80211_reg_rule *reg_rule)
|
||||
{
|
||||
|
@ -974,6 +973,13 @@ static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy)
|
|||
}
|
||||
#endif
|
||||
|
||||
static bool wiphy_strict_alpha2_regd(struct wiphy *wiphy)
|
||||
{
|
||||
if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY &&
|
||||
!(wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ignore_reg_update(struct wiphy *wiphy,
|
||||
enum nl80211_reg_initiator initiator)
|
||||
|
@ -1000,7 +1006,7 @@ static bool ignore_reg_update(struct wiphy *wiphy,
|
|||
* wiphy->regd will be set once the device has its own
|
||||
* desired regulatory domain set
|
||||
*/
|
||||
if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && !wiphy->regd &&
|
||||
if (wiphy_strict_alpha2_regd(wiphy) && !wiphy->regd &&
|
||||
initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
|
||||
!is_world_regdom(lr->alpha2)) {
|
||||
REG_DBG_PRINT("Ignoring regulatory request set by %s "
|
||||
|
@ -1706,8 +1712,8 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
|
|||
}
|
||||
EXPORT_SYMBOL(regulatory_hint);
|
||||
|
||||
void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
|
||||
const u8 *country_ie, u8 country_ie_len)
|
||||
void regulatory_hint_country_ie(struct wiphy *wiphy, enum ieee80211_band band,
|
||||
const u8 *country_ie, u8 country_ie_len)
|
||||
{
|
||||
char alpha2[2];
|
||||
enum environment_cap env = ENVIRON_ANY;
|
||||
|
|
|
@ -58,7 +58,7 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy,
|
|||
gfp_t gfp);
|
||||
|
||||
/**
|
||||
* regulatory_hint_11d - hints a country IE as a regulatory domain
|
||||
* regulatory_hint_country_ie - hints a country IE as a regulatory domain
|
||||
* @wiphy: the wireless device giving the hint (used only for reporting
|
||||
* conflicts)
|
||||
* @band: the band on which the country IE was received on. This determines
|
||||
|
@ -78,7 +78,7 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy,
|
|||
* not observed. For this reason if a triplet is seen with channel
|
||||
* information for a band the BSS is not present in it will be ignored.
|
||||
*/
|
||||
void regulatory_hint_11d(struct wiphy *wiphy,
|
||||
void regulatory_hint_country_ie(struct wiphy *wiphy,
|
||||
enum ieee80211_band band,
|
||||
const u8 *country_ie,
|
||||
u8 country_ie_len);
|
||||
|
|
|
@ -682,8 +682,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
|||
* - country_ie + 2, the start of the country ie data, and
|
||||
* - and country_ie[1] which is the IE length
|
||||
*/
|
||||
regulatory_hint_11d(wdev->wiphy, bss->channel->band,
|
||||
country_ie + 2, country_ie[1]);
|
||||
regulatory_hint_country_ie(wdev->wiphy, bss->channel->band,
|
||||
country_ie + 2, country_ie[1]);
|
||||
kfree(country_ie);
|
||||
}
|
||||
|
||||
|
|
|
@ -1249,7 +1249,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
|
|||
enum cfg80211_chan_mode chmode;
|
||||
int num_different_channels = 0;
|
||||
int total = 1;
|
||||
bool radar_required;
|
||||
bool radar_required = false;
|
||||
int i, j;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
@ -1264,14 +1264,20 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
|
|||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
case NL80211_IFTYPE_WDS:
|
||||
radar_required = !!(chan &&
|
||||
(chan->flags & IEEE80211_CHAN_RADAR));
|
||||
/* if the interface could potentially choose a DFS channel,
|
||||
* then mark DFS as required.
|
||||
*/
|
||||
if (!chan) {
|
||||
if (chanmode != CHAN_MODE_UNDEFINED && radar_detect)
|
||||
radar_required = true;
|
||||
break;
|
||||
}
|
||||
radar_required = !!(chan->flags & IEEE80211_CHAN_RADAR);
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
radar_required = false;
|
||||
break;
|
||||
case NUM_NL80211_IFTYPES:
|
||||
case NL80211_IFTYPE_UNSPECIFIED:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue