summaryrefslogtreecommitdiff
path: root/net/wireless
diff options
context:
space:
mode:
authorPaul Moore <pmoore@redhat.com>2014-01-28 23:44:16 +0400
committerPaul Moore <pmoore@redhat.com>2014-02-05 19:39:48 +0400
commit825e587af2e90e9b953849f3347a01d8f383d577 (patch)
treee48942a05882da47544e179c6a0c920e00137a6a /net/wireless
parent8ed814602876bec9bad2649ca17f34b499357a1c (diff)
parentd8ec26d7f8287f5788a494f56e8814210f0e64be (diff)
downloadlinux-825e587af2e90e9b953849f3347a01d8f383d577.tar.xz
Merge tag 'v3.13' into stable-3.14
Linux 3.13 Conflicts: security/selinux/hooks.c Trivial merge issue in selinux_inet_conn_request() likely due to me including patches that I sent to the stable folks in my next tree resulting in the patch hitting twice (I think). Thankfully it was an easy fix this time, but regardless, lesson learned, I will not do that again.
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/chan.c4
-rw-r--r--net/wireless/core.c9
-rw-r--r--net/wireless/core.h15
-rw-r--r--net/wireless/debugfs.c24
-rw-r--r--net/wireless/genregdb.awk6
-rw-r--r--net/wireless/ibss.c42
-rw-r--r--net/wireless/mlme.c6
-rw-r--r--net/wireless/nl80211.c368
-rw-r--r--net/wireless/radiotap.c4
-rw-r--r--net/wireless/reg.c53
-rw-r--r--net/wireless/reg.h4
-rw-r--r--net/wireless/scan.c4
-rw-r--r--net/wireless/sme.c26
-rw-r--r--net/wireless/sysfs.h4
-rw-r--r--net/wireless/util.c23
15 files changed, 364 insertions, 228 deletions
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 50f6195c8b70..9b8cc877eb19 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -328,6 +328,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
return cfg80211_get_chans_dfs_required(wiphy, chandef->center_freq2,
width);
}
+EXPORT_SYMBOL(cfg80211_chandef_dfs_required);
static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
u32 center_freq, u32 bandwidth,
@@ -503,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;
diff --git a/net/wireless/core.c b/net/wireless/core.c
index aff959e5a1b3..52b865fb7351 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -451,6 +451,15 @@ int wiphy_register(struct wiphy *wiphy)
int i;
u16 ifmodes = wiphy->interface_modes;
+ /* support for 5/10 MHz is broken due to nl80211 API mess - disable */
+ wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_5_10_MHZ;
+
+ /*
+ * There are major locking problems in nl80211/mac80211 for CSA,
+ * disable for all drivers until this has been reworked.
+ */
+ wiphy->flags &= ~WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+
#ifdef CONFIG_PM
if (WARN_ON(wiphy->wowlan &&
(wiphy->wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 3159e9c284c5..af10e59af2d8 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -234,10 +234,10 @@ struct cfg80211_beacon_registration {
};
/* free object */
-extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev);
+void cfg80211_dev_free(struct cfg80211_registered_device *rdev);
-extern int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
- char *newname);
+int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
+ char *newname);
void ieee80211_set_bitrate_flags(struct wiphy *wiphy);
@@ -382,15 +382,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
enum cfg80211_chan_mode chanmode,
u8 radar_detect);
-/**
- * cfg80211_chandef_dfs_required - checks if radar detection is required
- * @wiphy: the wiphy to validate against
- * @chandef: the channel definition to check
- * Return: 1 if radar detection is required, 0 if it is not, < 0 on error
- */
-int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
- const struct cfg80211_chan_def *c);
-
void cfg80211_set_dfs_state(struct wiphy *wiphy,
const struct cfg80211_chan_def *chandef,
enum nl80211_dfs_state dfs_state);
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
index 90d050036624..454157717efa 100644
--- a/net/wireless/debugfs.c
+++ b/net/wireless/debugfs.c
@@ -47,17 +47,19 @@ static int ht_print_chan(struct ieee80211_channel *chan,
return 0;
if (chan->flags & IEEE80211_CHAN_DISABLED)
- return snprintf(buf + offset,
- buf_size - offset,
- "%d Disabled\n",
- chan->center_freq);
-
- return snprintf(buf + offset,
- buf_size - offset,
- "%d HT40 %c%c\n",
- chan->center_freq,
- (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) ? ' ' : '-',
- (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) ? ' ' : '+');
+ return scnprintf(buf + offset,
+ buf_size - offset,
+ "%d Disabled\n",
+ chan->center_freq);
+
+ return scnprintf(buf + offset,
+ buf_size - offset,
+ "%d HT40 %c%c\n",
+ chan->center_freq,
+ (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) ?
+ ' ' : '-',
+ (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) ?
+ ' ' : '+');
}
static ssize_t ht40allow_map_read(struct file *file,
diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk
index 9392f8cbb901..42ed274e81f4 100644
--- a/net/wireless/genregdb.awk
+++ b/net/wireless/genregdb.awk
@@ -46,6 +46,12 @@ BEGIN {
sub(/:/, "", country)
printf "static const struct ieee80211_regdomain regdom_%s = {\n", country
printf "\t.alpha2 = \"%s\",\n", country
+ if ($NF ~ /DFS-ETSI/)
+ printf "\t.dfs_region = NL80211_DFS_ETSI,\n"
+ else if ($NF ~ /DFS-FCC/)
+ printf "\t.dfs_region = NL80211_DFS_FCC,\n"
+ else if ($NF ~ /DFS-JP/)
+ printf "\t.dfs_region = NL80211_DFS_JP,\n"
printf "\t.reg_rules = {\n"
active = 1
regdb = regdb "\t&regdom_" country ",\n"
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 403fe29c024d..89737ee2669a 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -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;
@@ -246,7 +262,7 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
/* try to find an IBSS channel if none requested ... */
if (!wdev->wext.ibss.chandef.chan) {
- wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
+ struct ieee80211_channel *new_chan = NULL;
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
struct ieee80211_supported_band *sband;
@@ -262,18 +278,19 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
continue;
if (chan->flags & IEEE80211_CHAN_DISABLED)
continue;
- wdev->wext.ibss.chandef.chan = chan;
- wdev->wext.ibss.chandef.center_freq1 =
- chan->center_freq;
+ new_chan = chan;
break;
}
- if (wdev->wext.ibss.chandef.chan)
+ if (new_chan)
break;
}
- if (!wdev->wext.ibss.chandef.chan)
+ if (!new_chan)
return -EINVAL;
+
+ cfg80211_chandef_create(&wdev->wext.ibss.chandef, new_chan,
+ NL80211_CHAN_NO_HT);
}
/* don't join -- SSID is not there */
@@ -347,9 +364,8 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
return err;
if (chan) {
- wdev->wext.ibss.chandef.chan = chan;
- wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
- wdev->wext.ibss.chandef.center_freq1 = freq;
+ cfg80211_chandef_create(&wdev->wext.ibss.chandef, chan,
+ NL80211_CHAN_NO_HT);
wdev->wext.ibss.channel_fixed = true;
} else {
/* cfg80211_ibss_wext_join will pick one if needed */
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 8d49c1ce3dea..6a6b1c8e907d 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -707,11 +707,13 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
if (c->dfs_state != NL80211_DFS_UNAVAILABLE)
continue;
- timeout = c->dfs_state_entered +
- IEEE80211_DFS_MIN_NOP_TIME_MS;
+ timeout = c->dfs_state_entered + msecs_to_jiffies(
+ IEEE80211_DFS_MIN_NOP_TIME_MS);
if (time_after_eq(jiffies, timeout)) {
c->dfs_state = NL80211_DFS_USABLE;
+ c->dfs_state_entered = jiffies;
+
cfg80211_chandef_create(&chandef, c,
NL80211_CHAN_NO_HT);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 626dc3b5fd8d..138dc3bb8b67 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -30,9 +30,9 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
struct cfg80211_crypto_settings *settings,
int cipher_limit);
-static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
+static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
struct genl_info *info);
-static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
+static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
struct genl_info *info);
/* the netlink family */
@@ -47,6 +47,25 @@ static struct genl_family nl80211_fam = {
.post_doit = nl80211_post_doit,
};
+/* multicast groups */
+enum nl80211_multicast_groups {
+ NL80211_MCGRP_CONFIG,
+ NL80211_MCGRP_SCAN,
+ NL80211_MCGRP_REGULATORY,
+ NL80211_MCGRP_MLME,
+ NL80211_MCGRP_TESTMODE /* keep last - ifdef! */
+};
+
+static const struct genl_multicast_group nl80211_mcgrps[] = {
+ [NL80211_MCGRP_CONFIG] = { .name = "config", },
+ [NL80211_MCGRP_SCAN] = { .name = "scan", },
+ [NL80211_MCGRP_REGULATORY] = { .name = "regulatory", },
+ [NL80211_MCGRP_MLME] = { .name = "mlme", },
+#ifdef CONFIG_NL80211_TESTMODE
+ [NL80211_MCGRP_TESTMODE] = { .name = "testmode", }
+#endif
+};
+
/* returns ERR_PTR values */
static struct wireless_dev *
__cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
@@ -354,6 +373,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 */
@@ -2665,7 +2687,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
NL80211_CMD_NEW_KEY);
if (!hdr)
- return -ENOBUFS;
+ goto nla_put_failure;
cookie.msg = msg;
cookie.idx = key_idx;
@@ -3896,9 +3918,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 +3967,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 +4151,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}
+ err = nl80211_parse_sta_channel_info(info, &params);
+ if (err)
+ return err;
+
err = nl80211_parse_sta_wme(info, &params);
if (err)
return err;
@@ -5283,6 +5349,10 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
err = -EINVAL;
goto out_free;
}
+
+ if (!wiphy->bands[band])
+ continue;
+
err = ieee80211_get_ratemask(wiphy->bands[band],
nla_data(attr),
nla_len(attr),
@@ -5591,6 +5661,9 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
if (err)
return err;
+ if (netif_carrier_ok(dev))
+ return -EBUSY;
+
if (wdev->cac_started)
return -EBUSY;
@@ -5634,15 +5707,27 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1];
u8 radar_detect_width = 0;
int err;
+ bool need_new_beacon = false;
if (!rdev->ops->channel_switch ||
!(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
return -EOPNOTSUPP;
- /* may add IBSS support later */
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ switch (dev->ieee80211_ptr->iftype) {
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_P2P_GO:
+ need_new_beacon = true;
+
+ /* useless if AP is not running */
+ if (!wdev->beacon_interval)
+ return -EINVAL;
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_MESH_POINT:
+ break;
+ default:
return -EOPNOTSUPP;
+ }
memset(&params, 0, sizeof(params));
@@ -5651,15 +5736,14 @@ 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 (!info->attrs[NL80211_ATTR_CSA_IES])
- return -EINVAL;
-
- /* useless if AP is not running */
- if (!wdev->beacon_interval)
+ if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES])
return -EINVAL;
params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
+ if (!need_new_beacon)
+ goto skip_beacons;
+
err = nl80211_parse_beacon(info->attrs, &params.beacon_after);
if (err)
return err;
@@ -5699,6 +5783,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}
+skip_beacons:
err = nl80211_parse_chandef(rdev, info, &params.chandef);
if (err)
return err;
@@ -5706,12 +5791,17 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef))
return -EINVAL;
- err = cfg80211_chandef_dfs_required(wdev->wiphy, &params.chandef);
- if (err < 0) {
- return err;
- } else if (err) {
- radar_detect_width = BIT(params.chandef.width);
- params.radar_required = true;
+ if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP ||
+ dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO ||
+ dev->ieee80211_ptr->iftype == NL80211_IFTYPE_ADHOC) {
+ err = cfg80211_chandef_dfs_required(wdev->wiphy,
+ &params.chandef);
+ if (err < 0) {
+ return err;
+ } else if (err) {
+ radar_detect_width = BIT(params.chandef.width);
+ params.radar_required = true;
+ }
}
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
@@ -6535,6 +6625,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);
@@ -6586,10 +6679,6 @@ static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
#ifdef CONFIG_NL80211_TESTMODE
-static struct genl_multicast_group nl80211_testmode_mcgrp = {
- .name = "testmode",
-};
-
static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -6798,8 +6887,8 @@ void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
nla_nest_end(skb, data);
genlmsg_end(skb, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), skb, 0,
- nl80211_testmode_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), skb, 0,
+ NL80211_MCGRP_TESTMODE, gfp);
}
EXPORT_SYMBOL(cfg80211_testmode_event);
#endif
@@ -8781,7 +8870,7 @@ static int nl80211_crit_protocol_stop(struct sk_buff *skb,
#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\
NL80211_FLAG_CHECK_NETDEV_UP)
-static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
+static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
struct genl_info *info)
{
struct cfg80211_registered_device *rdev;
@@ -8850,7 +8939,7 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
return 0;
}
-static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
+static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
struct genl_info *info)
{
if (info->user_ptr[1]) {
@@ -8867,7 +8956,7 @@ static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
rtnl_unlock();
}
-static struct genl_ops nl80211_ops[] = {
+static const struct genl_ops nl80211_ops[] = {
{
.cmd = NL80211_CMD_GET_WIPHY,
.doit = nl80211_get_wiphy,
@@ -9496,21 +9585,6 @@ static struct genl_ops nl80211_ops[] = {
},
};
-static struct genl_multicast_group nl80211_mlme_mcgrp = {
- .name = "mlme",
-};
-
-/* multicast groups */
-static struct genl_multicast_group nl80211_config_mcgrp = {
- .name = "config",
-};
-static struct genl_multicast_group nl80211_scan_mcgrp = {
- .name = "scan",
-};
-static struct genl_multicast_group nl80211_regulatory_mcgrp = {
- .name = "regulatory",
-};
-
/* notification functions */
void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
@@ -9527,8 +9601,8 @@ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
return;
}
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_config_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_CONFIG, GFP_KERNEL);
}
static int nl80211_add_scan_req(struct sk_buff *msg,
@@ -9563,8 +9637,9 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie))
goto nla_put_failure;
- if (req->flags)
- nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags);
+ if (req->flags &&
+ nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
+ goto nla_put_failure;
return 0;
nla_put_failure:
@@ -9637,8 +9712,8 @@ void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
return;
}
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_scan_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_SCAN, GFP_KERNEL);
}
void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
@@ -9656,8 +9731,8 @@ void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
return;
}
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_scan_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_SCAN, GFP_KERNEL);
}
void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
@@ -9675,8 +9750,8 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
return;
}
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_scan_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_SCAN, GFP_KERNEL);
}
void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
@@ -9694,8 +9769,8 @@ void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
return;
}
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_scan_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_SCAN, GFP_KERNEL);
}
void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
@@ -9712,8 +9787,8 @@ void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
return;
}
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_scan_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_SCAN, GFP_KERNEL);
}
/*
@@ -9767,8 +9842,8 @@ void nl80211_send_reg_change_event(struct regulatory_request *request)
genlmsg_end(msg, hdr);
rcu_read_lock();
- genlmsg_multicast_allns(msg, 0, nl80211_regulatory_mcgrp.id,
- GFP_ATOMIC);
+ genlmsg_multicast_allns(&nl80211_fam, msg, 0,
+ NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
rcu_read_unlock();
return;
@@ -9803,8 +9878,8 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -9891,8 +9966,8 @@ static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -9947,8 +10022,8 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -9986,8 +10061,8 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10024,8 +10099,8 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, GFP_KERNEL);
return;
nla_put_failure:
@@ -10058,8 +10133,8 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10099,8 +10174,8 @@ void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10138,8 +10213,8 @@ void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10191,8 +10266,8 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
genlmsg_end(msg, hdr);
rcu_read_lock();
- genlmsg_multicast_allns(msg, 0, nl80211_regulatory_mcgrp.id,
- GFP_ATOMIC);
+ genlmsg_multicast_allns(&nl80211_fam, msg, 0,
+ NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
rcu_read_unlock();
return;
@@ -10237,8 +10312,8 @@ static void nl80211_send_remain_on_chan_event(
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10292,8 +10367,8 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
return;
}
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
}
EXPORT_SYMBOL(cfg80211_new_sta);
@@ -10322,8 +10397,8 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp)
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10358,8 +10433,8 @@ void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10520,8 +10595,8 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10569,8 +10644,8 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10614,8 +10689,8 @@ static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10672,8 +10747,8 @@ nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10719,8 +10794,8 @@ static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10740,7 +10815,9 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
wdev_lock(wdev);
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
- wdev->iftype != NL80211_IFTYPE_P2P_GO))
+ wdev->iftype != NL80211_IFTYPE_P2P_GO &&
+ wdev->iftype != NL80211_IFTYPE_ADHOC &&
+ wdev->iftype != NL80211_IFTYPE_MESH_POINT))
goto out;
wdev->channel = chandef->chan;
@@ -10794,8 +10871,8 @@ void cfg80211_cqm_txe_notify(struct net_device *dev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10843,8 +10920,8 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10890,8 +10967,8 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10930,8 +11007,8 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -11021,6 +11098,8 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
struct nlattr *reasons;
reasons = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
+ if (!reasons)
+ goto free_msg;
if (wakeup->disconnect &&
nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT))
@@ -11046,16 +11125,18 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
wakeup->pattern_idx))
goto free_msg;
- if (wakeup->tcp_match)
- nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH);
+ if (wakeup->tcp_match &&
+ nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH))
+ goto free_msg;
- if (wakeup->tcp_connlost)
- nla_put_flag(msg,
- NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST);
+ if (wakeup->tcp_connlost &&
+ nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST))
+ goto free_msg;
- if (wakeup->tcp_nomoretokens)
- nla_put_flag(msg,
- NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS);
+ if (wakeup->tcp_nomoretokens &&
+ nla_put_flag(msg,
+ NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS))
+ goto free_msg;
if (wakeup->packet) {
u32 pkt_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211;
@@ -11082,8 +11163,8 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
free_msg:
@@ -11124,8 +11205,8 @@ void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -11191,24 +11272,29 @@ void cfg80211_ft_event(struct net_device *netdev,
return;
hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT);
- if (!hdr) {
- nlmsg_free(msg);
- return;
- }
+ if (!hdr)
+ goto out;
- nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
- nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
- nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap);
- if (ft_event->ies)
- nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies);
- if (ft_event->ric_ies)
- nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
- ft_event->ric_ies);
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+ nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
+ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap))
+ goto out;
+
+ if (ft_event->ies &&
+ nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies))
+ goto out;
+ if (ft_event->ric_ies &&
+ nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
+ ft_event->ric_ies))
+ goto out;
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, GFP_KERNEL);
+ return;
+ out:
+ nlmsg_free(msg);
}
EXPORT_SYMBOL(cfg80211_ft_event);
@@ -11257,33 +11343,11 @@ int nl80211_init(void)
{
int err;
- err = genl_register_family_with_ops(&nl80211_fam,
- nl80211_ops, ARRAY_SIZE(nl80211_ops));
+ err = genl_register_family_with_ops_groups(&nl80211_fam, nl80211_ops,
+ nl80211_mcgrps);
if (err)
return err;
- err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp);
- if (err)
- goto err_out;
-
- err = genl_register_mc_group(&nl80211_fam, &nl80211_scan_mcgrp);
- if (err)
- goto err_out;
-
- err = genl_register_mc_group(&nl80211_fam, &nl80211_regulatory_mcgrp);
- if (err)
- goto err_out;
-
- err = genl_register_mc_group(&nl80211_fam, &nl80211_mlme_mcgrp);
- if (err)
- goto err_out;
-
-#ifdef CONFIG_NL80211_TESTMODE
- err = genl_register_mc_group(&nl80211_fam, &nl80211_testmode_mcgrp);
- if (err)
- goto err_out;
-#endif
-
err = netlink_register_notifier(&nl80211_netlink_notifier);
if (err)
goto err_out;
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c
index a271c27fac77..722da616438c 100644
--- a/net/wireless/radiotap.c
+++ b/net/wireless/radiotap.c
@@ -124,6 +124,10 @@ int ieee80211_radiotap_iterator_init(
/* find payload start allowing for extended bitmap(s) */
if (iterator->_bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT)) {
+ if ((unsigned long)iterator->_arg -
+ (unsigned long)iterator->_rtheader + sizeof(uint32_t) >
+ (unsigned long)iterator->_max_length)
+ return -EINVAL;
while (get_unaligned_le32(iterator->_arg) &
(1 << IEEE80211_RADIOTAP_EXT)) {
iterator->_arg += sizeof(uint32_t);
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index de06d5d1287f..7da67fd0b418 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -172,11 +172,21 @@ static const struct ieee80211_regdomain world_regdom = {
NL80211_RRF_NO_IBSS |
NL80211_RRF_NO_OFDM),
/* IEEE 802.11a, channel 36..48 */
- REG_RULE(5180-10, 5240+10, 80, 6, 20,
+ REG_RULE(5180-10, 5240+10, 160, 6, 20,
NL80211_RRF_PASSIVE_SCAN |
NL80211_RRF_NO_IBSS),
- /* NB: 5260 MHz - 5700 MHz requires DFS */
+ /* IEEE 802.11a, channel 52..64 - DFS required */
+ REG_RULE(5260-10, 5320+10, 160, 6, 20,
+ NL80211_RRF_PASSIVE_SCAN |
+ NL80211_RRF_NO_IBSS |
+ NL80211_RRF_DFS),
+
+ /* IEEE 802.11a, channel 100..144 - DFS required */
+ REG_RULE(5500-10, 5720+10, 160, 6, 20,
+ NL80211_RRF_PASSIVE_SCAN |
+ NL80211_RRF_NO_IBSS |
+ NL80211_RRF_DFS),
/* IEEE 802.11a, channel 149..165 */
REG_RULE(5745-10, 5825+10, 80, 6, 20,
@@ -758,24 +768,25 @@ const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
}
EXPORT_SYMBOL(freq_reg_info);
-#ifdef CONFIG_CFG80211_REG_DEBUG
-static const char *reg_initiator_name(enum nl80211_reg_initiator initiator)
+const char *reg_initiator_name(enum nl80211_reg_initiator initiator)
{
switch (initiator) {
case NL80211_REGDOM_SET_BY_CORE:
- return "Set by core";
+ return "core";
case NL80211_REGDOM_SET_BY_USER:
- return "Set by user";
+ return "user";
case NL80211_REGDOM_SET_BY_DRIVER:
- return "Set by driver";
+ return "driver";
case NL80211_REGDOM_SET_BY_COUNTRY_IE:
- return "Set by country IE";
+ return "country IE";
default:
WARN_ON(1);
- return "Set by bug";
+ return "bug";
}
}
+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)
{
@@ -962,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)
@@ -969,14 +987,17 @@ static bool ignore_reg_update(struct wiphy *wiphy,
struct regulatory_request *lr = get_last_request();
if (!lr) {
- REG_DBG_PRINT("Ignoring regulatory request %s since last_request is not set\n",
+ REG_DBG_PRINT("Ignoring regulatory request set by %s "
+ "since last_request is not set\n",
reg_initiator_name(initiator));
return true;
}
if (initiator == NL80211_REGDOM_SET_BY_CORE &&
wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) {
- REG_DBG_PRINT("Ignoring regulatory request %s since the driver uses its own custom regulatory domain\n",
+ REG_DBG_PRINT("Ignoring regulatory request set by %s "
+ "since the driver uses its own custom "
+ "regulatory domain\n",
reg_initiator_name(initiator));
return true;
}
@@ -985,10 +1006,12 @@ 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 %s since the driver requires its own regulatory domain to be set first\n",
+ REG_DBG_PRINT("Ignoring regulatory request set by %s "
+ "since the driver requires its own regulatory "
+ "domain to be set first\n",
reg_initiator_name(initiator));
return true;
}
@@ -1689,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;
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index af2d5f8a5d82..9677e3c13da9 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -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);
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index eeb71480f1af..d4397eba5408 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -254,10 +254,10 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
rdev = container_of(wk, struct cfg80211_registered_device,
sched_scan_results_wk);
- request = rdev->sched_scan_req;
-
rtnl_lock();
+ request = rdev->sched_scan_req;
+
/* we don't have sched_scan_req anymore if the scan is stopping */
if (request) {
if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 20e86a95dc4e..d3c5bd7c6b51 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -632,6 +632,16 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
}
#endif
+ if (!bss && (status == WLAN_STATUS_SUCCESS)) {
+ WARN_ON_ONCE(!wiphy_to_dev(wdev->wiphy)->ops->connect);
+ bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
+ wdev->ssid, wdev->ssid_len,
+ WLAN_CAPABILITY_ESS,
+ WLAN_CAPABILITY_ESS);
+ if (bss)
+ cfg80211_hold_bss(bss_from_pub(bss));
+ }
+
if (wdev->current_bss) {
cfg80211_unhold_bss(wdev->current_bss);
cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
@@ -649,16 +659,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
return;
}
- if (!bss) {
- WARN_ON_ONCE(!wiphy_to_dev(wdev->wiphy)->ops->connect);
- bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
- wdev->ssid, wdev->ssid_len,
- WLAN_CAPABILITY_ESS,
- WLAN_CAPABILITY_ESS);
- if (WARN_ON(!bss))
- return;
- cfg80211_hold_bss(bss_from_pub(bss));
- }
+ if (WARN_ON(!bss))
+ return;
wdev->current_bss = bss_from_pub(bss);
@@ -682,8 +684,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);
}
diff --git a/net/wireless/sysfs.h b/net/wireless/sysfs.h
index 65acbebd3711..b533ed71daff 100644
--- a/net/wireless/sysfs.h
+++ b/net/wireless/sysfs.h
@@ -1,8 +1,8 @@
#ifndef __WIRELESS_SYSFS_H
#define __WIRELESS_SYSFS_H
-extern int wiphy_sysfs_init(void);
-extern void wiphy_sysfs_exit(void);
+int wiphy_sysfs_init(void);
+void wiphy_sysfs_exit(void);
extern struct class ieee80211_class;
diff --git a/net/wireless/util.c b/net/wireless/util.c
index ce090c1c5e4f..935dea9485da 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -10,6 +10,7 @@
#include <net/cfg80211.h>
#include <net/ip.h>
#include <net/dsfield.h>
+#include <linux/if_vlan.h>
#include "core.h"
#include "rdev-ops.h"
@@ -691,6 +692,7 @@ EXPORT_SYMBOL(ieee80211_amsdu_to_8023s);
unsigned int cfg80211_classify8021d(struct sk_buff *skb)
{
unsigned int dscp;
+ unsigned char vlan_priority;
/* skb->priority values from 256->263 are magic values to
* directly indicate a specific 802.1d priority. This is used
@@ -700,6 +702,13 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb)
if (skb->priority >= 256 && skb->priority <= 263)
return skb->priority - 256;
+ if (vlan_tx_tag_present(skb)) {
+ vlan_priority = (vlan_tx_tag_get(skb) & VLAN_PRIO_MASK)
+ >> VLAN_PRIO_SHIFT;
+ if (vlan_priority > 0)
+ return vlan_priority;
+ }
+
switch (skb->protocol) {
case htons(ETH_P_IP):
dscp = ipv4_get_dsfield(ip_hdr(skb)) & 0xfc;
@@ -1240,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();
@@ -1255,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: