Commit 3b3e808c authored by David S. Miller's avatar David S. Miller

Merge tag 'mac80211-next-for-net-next-2020-02-24' of...

Merge tag 'mac80211-next-for-net-next-2020-02-24' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next

Johannes Berg says:

====================
A new set of changes:
 * lots of small documentation fixes, from Jérôme Pouiller
 * beacon protection (BIGTK) support from Jouni Malinen
 * some initial code for TID configuration, from Tamizh chelvam
 * I reverted some new API before it's actually used, because
   it's wrong to mix controlled port and preauth
 * a few other cleanups/fixes
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 13ef6ae8 370f51d5
......@@ -2947,6 +2947,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
NL80211_FEATURE_DYNAMIC_SMPS |
NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_BEACON_PROTECTION);
hw->wiphy->interface_modes = param->iftypes;
......
This diff is collapsed.
......@@ -3776,6 +3776,9 @@ enum ieee80211_reconfig_type {
*
* @start_pmsr: start peer measurement (e.g. FTM) (this call can sleep)
* @abort_pmsr: abort peer measurement (this call can sleep)
* @set_tid_config: Apply TID specific configurations. This callback may sleep.
* @reset_tid_config: Reset TID specific configuration for the peer.
* This callback may sleep.
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
......@@ -4080,6 +4083,13 @@ struct ieee80211_ops {
struct cfg80211_pmsr_request *request);
void (*abort_pmsr)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct cfg80211_pmsr_request *request);
int (*set_tid_config)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct cfg80211_tid_config *tid_conf);
int (*reset_tid_config)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u8 tids);
};
/**
......
......@@ -264,6 +264,29 @@
* %NL80211_ATTR_VLAN_ID.
*/
/**
* DOC: TID configuration
*
* TID config support can be checked in the %NL80211_ATTR_TID_CONFIG
* attribute given in wiphy capabilities.
*
* The necessary configuration parameters are mentioned in
* &enum nl80211_tid_config_attr and it will be passed to the
* %NL80211_CMD_SET_TID_CONFIG command in %NL80211_ATTR_TID_CONFIG.
*
* If the configuration needs to be applied for specific peer then the MAC
* address of the peer needs to be passed in %NL80211_ATTR_MAC, otherwise the
* configuration will be applied for all the connected peers in the vif except
* any peers that have peer specific configuration for the TID by default; if
* the %NL80211_TID_CONFIG_ATTR_OVERRIDE flag is set, peer specific values
* will be overwritten.
*
* All this configuration is valid only for STA's current connection
* i.e. the configuration will be reset to default when the STA connects back
* after disconnection/roaming, and this configuration will be cleared when
* the interface goes down.
*/
/**
* enum nl80211_commands - supported nl80211 commands
*
......@@ -1039,14 +1062,11 @@
* a control port frame and as a notification that a control port frame
* has been received. %NL80211_ATTR_FRAME is used to specify the
* frame contents. The frame is the raw EAPoL data, without ethernet or
* 802.11 headers. An optional %NL80211_ATTR_SRC_MAC can be used to send
* pre-auth frames to STAs on behalf of other APs.
* 802.11 headers.
* When used as an event indication %NL80211_ATTR_CONTROL_PORT_ETHERTYPE,
* %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT and %NL80211_ATTR_MAC are added
* indicating the protocol type of the received frame; whether the frame
* was received unencrypted and the MAC address of the peer respectively.
* %NL80211_ATTR_DST_MAC can be used to forward pre-auth frames in
* userspace while using AP mode.
*
* @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded.
*
......@@ -1128,6 +1148,9 @@
* peer MAC address and %NL80211_ATTR_FRAME is used to specify the frame
* content. The frame is ethernet data.
*
* @NL80211_CMD_SET_TID_CONFIG: Data frame TID specific configuration
* is passed using %NL80211_ATTR_TID_CONFIG attribute.
*
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
......@@ -1352,6 +1375,8 @@ enum nl80211_commands {
NL80211_CMD_PROBE_MESH_LINK,
NL80211_CMD_SET_TID_CONFIG,
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
......@@ -2412,8 +2437,10 @@ enum nl80211_commands {
* %NL80211_ATTR_AKM_SUITES are default capabilities if AKM suites not
* advertised for a specific interface type.
*
* @NL80211_ATTR_SRC_MAC: MAC address used in control port over nl80211 transmit
* @NL80211_ATTR_DST_MAC: MAC address used in control port over nl80211 receive
* @NL80211_ATTR_TID_CONFIG: TID specific configuration in a
* nested attribute with &enum nl80211_tid_config_attr sub-attributes;
* on output (in wiphy attributes) it contains only the feature sub-
* attributes.
*
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
......@@ -2883,8 +2910,7 @@ enum nl80211_attrs {
NL80211_ATTR_IFTYPE_AKM_SUITES,
NL80211_ATTR_SRC_MAC,
NL80211_ATTR_DST_MAC,
NL80211_ATTR_TID_CONFIG,
/* add attributes here, update the policy in nl80211.c */
......@@ -4559,6 +4585,7 @@ enum nl80211_key_default_types {
* See &enum nl80211_key_default_types.
* @NL80211_KEY_MODE: the mode from enum nl80211_key_mode.
* Defaults to @NL80211_KEY_RX_TX.
* @NL80211_KEY_DEFAULT_BEACON: flag indicating default Beacon frame key
*
* @__NL80211_KEY_AFTER_LAST: internal
* @NL80211_KEY_MAX: highest key attribute
......@@ -4574,6 +4601,7 @@ enum nl80211_key_attributes {
NL80211_KEY_TYPE,
NL80211_KEY_DEFAULT_TYPES,
NL80211_KEY_MODE,
NL80211_KEY_DEFAULT_BEACON,
/* keep last */
__NL80211_KEY_AFTER_LAST,
......@@ -4729,6 +4757,69 @@ enum nl80211_tx_power_setting {
NL80211_TX_POWER_FIXED,
};
/**
* enum nl80211_tid_config - TID config state
* @NL80211_TID_CONFIG_ENABLE: Enable config for the TID
* @NL80211_TID_CONFIG_DISABLE: Disable config for the TID
*/
enum nl80211_tid_config {
NL80211_TID_CONFIG_ENABLE,
NL80211_TID_CONFIG_DISABLE,
};
/* enum nl80211_tid_config_attr - TID specific configuration.
* @NL80211_TID_CONFIG_ATTR_PAD: pad attribute for 64-bit values
* @NL80211_TID_CONFIG_ATTR_VIF_SUPP: a bitmap (u64) of attributes supported
* for per-vif configuration; doesn't list the ones that are generic
* (%NL80211_TID_CONFIG_ATTR_TIDS, %NL80211_TID_CONFIG_ATTR_OVERRIDE).
* @NL80211_TID_CONFIG_ATTR_PEER_SUPP: same as the previous per-vif one, but
* per peer instead.
* @NL80211_TID_CONFIG_ATTR_OVERRIDE: flag attribue, if no peer
* is selected, if set indicates that the new configuration overrides
* all previous peer configurations, otherwise previous peer specific
* configurations should be left untouched. If peer is selected then
* it will reset particular TID configuration of that peer and it will
* not accept other TID config attributes along with peer.
* @NL80211_TID_CONFIG_ATTR_TIDS: a bitmask value of TIDs (bit 0 to 7)
* Its type is u16.
* @NL80211_TID_CONFIG_ATTR_NOACK: Configure ack policy for the TID.
* specified in %NL80211_TID_CONFIG_ATTR_TID. see %enum nl80211_tid_config.
* Its type is u8.
* @NL80211_TID_CONFIG_ATTR_RETRY_SHORT: Number of retries used with data frame
* transmission, user-space sets this configuration in
* &NL80211_CMD_SET_TID_CONFIG. It is u8 type, min value is 1 and
* the max value is advertised by the driver in this attribute on
* output in wiphy capabilities.
* @NL80211_TID_CONFIG_ATTR_RETRY_LONG: Number of retries used with data frame
* transmission, user-space sets this configuration in
* &NL80211_CMD_SET_TID_CONFIG. Its type is u8, min value is 1 and
* the max value is advertised by the driver in this attribute on
* output in wiphy capabilities.
* @NL80211_TID_CONFIG_ATTR_AMPDU_CTRL: Enable/Disable aggregation for the TIDs
* specified in %NL80211_TID_CONFIG_ATTR_TIDS. Its type is u8, using
* the values from &nl80211_tid_config.
* @NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL: Enable/Disable RTS_CTS for the TIDs
* specified in %NL80211_TID_CONFIG_ATTR_TIDS. It is u8 type, using
* the values from &nl80211_tid_config.
*/
enum nl80211_tid_config_attr {
__NL80211_TID_CONFIG_ATTR_INVALID,
NL80211_TID_CONFIG_ATTR_PAD,
NL80211_TID_CONFIG_ATTR_VIF_SUPP,
NL80211_TID_CONFIG_ATTR_PEER_SUPP,
NL80211_TID_CONFIG_ATTR_OVERRIDE,
NL80211_TID_CONFIG_ATTR_TIDS,
NL80211_TID_CONFIG_ATTR_NOACK,
NL80211_TID_CONFIG_ATTR_RETRY_SHORT,
NL80211_TID_CONFIG_ATTR_RETRY_LONG,
NL80211_TID_CONFIG_ATTR_AMPDU_CTRL,
NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL,
/* keep last */
__NL80211_TID_CONFIG_ATTR_AFTER_LAST,
NL80211_TID_CONFIG_ATTR_MAX = __NL80211_TID_CONFIG_ATTR_AFTER_LAST - 1
};
/**
* enum nl80211_packet_pattern_attr - packet pattern attribute
* @__NL80211_PKTPAT_INVALID: invalid number for nested attribute
......@@ -5548,9 +5639,8 @@ enum nl80211_feature_flags {
* feature, which prevents bufferbloat by using the expected transmission
* time to limit the amount of data buffered in the hardware.
*
* @NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_MAC_ADDRS: The driver
* can use src and dst MAC addresses with control port over nl80211 rx
* and tx operations.
* @NL80211_EXT_FEATURE_BEACON_PROTECTION: The driver supports Beacon protection
* and can receive key configuration for BIGTK using key indexes 6 and 7.
*
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
......@@ -5599,7 +5689,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_SAE_OFFLOAD,
NL80211_EXT_FEATURE_VLAN_OFFLOAD,
NL80211_EXT_FEATURE_AQL,
NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_MAC_ADDRS,
NL80211_EXT_FEATURE_BEACON_PROTECTION,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
......
......@@ -26,12 +26,20 @@ void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad,
{
SHASH_DESC_ON_STACK(desc, tfm);
u8 out[AES_BLOCK_SIZE];
const __le16 *fc;
desc->tfm = tfm;
crypto_shash_init(desc);
crypto_shash_update(desc, aad, AAD_LEN);
crypto_shash_update(desc, data, data_len - CMAC_TLEN);
fc = (const __le16 *)aad;
if (ieee80211_is_beacon(*fc)) {
/* mask Timestamp field to zero */
crypto_shash_update(desc, zero, 8);
crypto_shash_update(desc, data + 8, data_len - 8 - CMAC_TLEN);
} else {
crypto_shash_update(desc, data, data_len - CMAC_TLEN);
}
crypto_shash_finup(desc, zero, CMAC_TLEN, out);
memcpy(mic, out, CMAC_TLEN);
......@@ -41,12 +49,21 @@ void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad,
const u8 *data, size_t data_len, u8 *mic)
{
SHASH_DESC_ON_STACK(desc, tfm);
const __le16 *fc;
desc->tfm = tfm;
crypto_shash_init(desc);
crypto_shash_update(desc, aad, AAD_LEN);
crypto_shash_update(desc, data, data_len - CMAC_TLEN_256);
fc = (const __le16 *)aad;
if (ieee80211_is_beacon(*fc)) {
/* mask Timestamp field to zero */
crypto_shash_update(desc, zero, 8);
crypto_shash_update(desc, data + 8,
data_len - 8 - CMAC_TLEN_256);
} else {
crypto_shash_update(desc, data, data_len - CMAC_TLEN_256);
}
crypto_shash_finup(desc, zero, CMAC_TLEN_256, mic);
}
......
......@@ -17,10 +17,11 @@
int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
const u8 *data, size_t data_len, u8 *mic)
{
struct scatterlist sg[4];
struct scatterlist sg[5];
u8 *zero, *__aad, iv[AES_BLOCK_SIZE];
struct aead_request *aead_req;
int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
const __le16 *fc;
if (data_len < GMAC_MIC_LEN)
return -EINVAL;
......@@ -33,11 +34,22 @@ int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
__aad = zero + GMAC_MIC_LEN;
memcpy(__aad, aad, GMAC_AAD_LEN);
sg_init_table(sg, 4);
sg_set_buf(&sg[0], __aad, GMAC_AAD_LEN);
sg_set_buf(&sg[1], data, data_len - GMAC_MIC_LEN);
sg_set_buf(&sg[2], zero, GMAC_MIC_LEN);
sg_set_buf(&sg[3], mic, GMAC_MIC_LEN);
fc = (const __le16 *)aad;
if (ieee80211_is_beacon(*fc)) {
/* mask Timestamp field to zero */
sg_init_table(sg, 5);
sg_set_buf(&sg[0], __aad, GMAC_AAD_LEN);
sg_set_buf(&sg[1], zero, 8);
sg_set_buf(&sg[2], data + 8, data_len - 8 - GMAC_MIC_LEN);
sg_set_buf(&sg[3], zero, GMAC_MIC_LEN);
sg_set_buf(&sg[4], mic, GMAC_MIC_LEN);
} else {
sg_init_table(sg, 4);
sg_set_buf(&sg[0], __aad, GMAC_AAD_LEN);
sg_set_buf(&sg[1], data, data_len - GMAC_MIC_LEN);
sg_set_buf(&sg[2], zero, GMAC_MIC_LEN);
sg_set_buf(&sg[3], mic, GMAC_MIC_LEN);
}
memcpy(iv, nonce, GMAC_NONCE_LEN);
memset(iv + GMAC_NONCE_LEN, 0, sizeof(iv) - GMAC_NONCE_LEN);
......
......@@ -568,7 +568,8 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
if (pairwise && key_idx < NUM_DEFAULT_KEYS)
key = rcu_dereference(sta->ptk[key_idx]);
else if (!pairwise &&
key_idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
key_idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
NUM_DEFAULT_BEACON_KEYS)
key = rcu_dereference(sta->gtk[key_idx]);
} else
key = rcu_dereference(sdata->keys[key_idx]);
......@@ -680,6 +681,17 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
return 0;
}
static int ieee80211_config_default_beacon_key(struct wiphy *wiphy,
struct net_device *dev,
u8 key_idx)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
ieee80211_set_default_beacon_key(sdata, key_idx);
return 0;
}
void sta_set_rate_info_tx(struct sta_info *sta,
const struct ieee80211_tx_rate *rate,
struct rate_info *rinfo)
......@@ -3874,6 +3886,60 @@ ieee80211_abort_pmsr(struct wiphy *wiphy, struct wireless_dev *dev,
return drv_abort_pmsr(local, sdata, request);
}
static int ieee80211_set_tid_config(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_tid_config *tid_conf)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct sta_info *sta;
int ret;
if (!sdata->local->ops->set_tid_config)
return -EOPNOTSUPP;
if (!tid_conf->peer)
return drv_set_tid_config(sdata->local, sdata, NULL, tid_conf);
mutex_lock(&sdata->local->sta_mtx);
sta = sta_info_get_bss(sdata, tid_conf->peer);
if (!sta) {
mutex_unlock(&sdata->local->sta_mtx);
return -ENOENT;
}
ret = drv_set_tid_config(sdata->local, sdata, &sta->sta, tid_conf);
mutex_unlock(&sdata->local->sta_mtx);
return ret;
}
static int ieee80211_reset_tid_config(struct wiphy *wiphy,
struct net_device *dev,
const u8 *peer, u8 tid)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct sta_info *sta;
int ret;
if (!sdata->local->ops->reset_tid_config)
return -EOPNOTSUPP;
if (!peer)
return drv_reset_tid_config(sdata->local, sdata, NULL, tid);
mutex_lock(&sdata->local->sta_mtx);
sta = sta_info_get_bss(sdata, peer);
if (!sta) {
mutex_unlock(&sdata->local->sta_mtx);
return -ENOENT;
}
ret = drv_reset_tid_config(sdata->local, sdata, &sta->sta, tid);
mutex_unlock(&sdata->local->sta_mtx);
return ret;
}
const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
......@@ -3885,6 +3951,7 @@ const struct cfg80211_ops mac80211_config_ops = {
.get_key = ieee80211_get_key,
.set_default_key = ieee80211_config_default_key,
.set_default_mgmt_key = ieee80211_config_default_mgmt_key,
.set_default_beacon_key = ieee80211_config_default_beacon_key,
.start_ap = ieee80211_start_ap,
.change_beacon = ieee80211_change_beacon,
.stop_ap = ieee80211_stop_ap,
......@@ -3973,4 +4040,6 @@ const struct cfg80211_ops mac80211_config_ops = {
.start_pmsr = ieee80211_start_pmsr,
.abort_pmsr = ieee80211_abort_pmsr,
.probe_mesh_link = ieee80211_probe_mesh_link,
.set_tid_config = ieee80211_set_tid_config,
.reset_tid_config = ieee80211_reset_tid_config,
};
......@@ -433,6 +433,37 @@ void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sda
sdata->debugfs.default_mgmt_key = NULL;
}
void
ieee80211_debugfs_key_add_beacon_default(struct ieee80211_sub_if_data *sdata)
{
char buf[50];
struct ieee80211_key *key;
if (!sdata->vif.debugfs_dir)
return;
key = key_mtx_dereference(sdata->local,
sdata->default_beacon_key);
if (key) {
sprintf(buf, "../keys/%d", key->debugfs.cnt);
sdata->debugfs.default_beacon_key =
debugfs_create_symlink("default_beacon_key",
sdata->vif.debugfs_dir, buf);
} else {
ieee80211_debugfs_key_remove_beacon_default(sdata);
}
}
void
ieee80211_debugfs_key_remove_beacon_default(struct ieee80211_sub_if_data *sdata)
{
if (!sdata)
return;
debugfs_remove(sdata->debugfs.default_beacon_key);
sdata->debugfs.default_beacon_key = NULL;
}
void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
struct sta_info *sta)
{
......
......@@ -10,6 +10,10 @@ void ieee80211_debugfs_key_add_mgmt_default(
struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_key_remove_mgmt_default(
struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_key_add_beacon_default(
struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_key_remove_beacon_default(
struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
struct sta_info *sta);
#else
......@@ -26,6 +30,12 @@ static inline void ieee80211_debugfs_key_add_mgmt_default(
static inline void ieee80211_debugfs_key_remove_mgmt_default(
struct ieee80211_sub_if_data *sdata)
{}
static inline void ieee80211_debugfs_key_add_beacon_default(
struct ieee80211_sub_if_data *sdata)
{}
static inline void ieee80211_debugfs_key_remove_beacon_default(
struct ieee80211_sub_if_data *sdata)
{}
static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
struct sta_info *sta)
{}
......
......@@ -1358,4 +1358,31 @@ static inline void drv_del_nan_func(struct ieee80211_local *local,
trace_drv_return_void(local);
}
static inline int drv_set_tid_config(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct ieee80211_sta *sta,
struct cfg80211_tid_config *tid_conf)
{
int ret;
might_sleep();
ret = local->ops->set_tid_config(&local->hw, &sdata->vif, sta,
tid_conf);
trace_drv_return_int(local, ret);
return ret;
}
static inline int drv_reset_tid_config(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct ieee80211_sta *sta, u8 tid)
{
int ret;
might_sleep();
ret = local->ops->reset_tid_config(&local->hw, &sdata->vif, sta, tid);
trace_drv_return_int(local, ret);
return ret;
}
#endif /* __MAC80211_DRIVER_OPS */
......@@ -901,10 +901,13 @@ struct ieee80211_sub_if_data {
/* bit field of ACM bits (BIT(802.1D tag)) */
u8 wmm_acm;
struct ieee80211_key __rcu *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
struct ieee80211_key __rcu *keys[NUM_DEFAULT_KEYS +
NUM_DEFAULT_MGMT_KEYS +
NUM_DEFAULT_BEACON_KEYS];
struct ieee80211_key __rcu *default_unicast_key;
struct ieee80211_key __rcu *default_multicast_key;
struct ieee80211_key __rcu *default_mgmt_key;
struct ieee80211_key __rcu *default_beacon_key;
u16 sequence_number;
__be16 control_port_protocol;
......@@ -978,6 +981,7 @@ struct ieee80211_sub_if_data {
struct dentry *default_unicast_key;
struct dentry *default_multicast_key;
struct dentry *default_mgmt_key;
struct dentry *default_beacon_key;
} debugfs;
#endif
......@@ -1792,8 +1796,7 @@ void ieee80211_check_fast_xmit_iface(struct ieee80211_sub_if_data *sdata);
void ieee80211_clear_fast_xmit(struct sta_info *sta);
int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
const u8 *buf, size_t len,
const u8 *dest, const u8 *src, __be16 proto,
bool unencrypted);
const u8 *dest, __be16 proto, bool unencrypted);
int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
const u8 *buf, size_t len);
......
......@@ -407,6 +407,31 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
mutex_unlock(&sdata->local->key_mtx);
}
static void
__ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata, int idx)
{
struct ieee80211_key *key = NULL;
assert_key_lock(sdata->local);
if (idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS &&
idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
NUM_DEFAULT_BEACON_KEYS)
key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
rcu_assign_pointer(sdata->default_beacon_key, key);
ieee80211_debugfs_key_update_default(sdata);
}
void ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata,
int idx)
{
mutex_lock(&sdata->local->key_mtx);
__ieee80211_set_default_beacon_key(sdata, idx);
mutex_unlock(&sdata->local->key_mtx);
}
static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta,
bool pairwise,
......@@ -415,7 +440,7 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
{
int idx;
int ret = 0;
bool defunikey, defmultikey, defmgmtkey;
bool defunikey, defmultikey, defmgmtkey, defbeaconkey;
/* caller must provide at least one old/new */
if (WARN_ON(!new && !old))
......@@ -480,6 +505,9 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
defmgmtkey = old &&
old == key_mtx_dereference(sdata->local,
sdata->default_mgmt_key);
defbeaconkey = old &&
old == key_mtx_dereference(sdata->local,
sdata->default_beacon_key);
if (defunikey && !new)
__ieee80211_set_default_key(sdata, -1, true, false);
......@@ -487,6 +515,8 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
__ieee80211_set_default_key(sdata, -1, false, true);
if (defmgmtkey && !new)
__ieee80211_set_default_mgmt_key(sdata, -1);
if (defbeaconkey && !new)
__ieee80211_set_default_beacon_key(sdata, -1);
rcu_assign_pointer(sdata->keys[idx], new);
if (defunikey && new)
......@@ -498,6 +528,9 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
if (defmgmtkey && new)
__ieee80211_set_default_mgmt_key(sdata,
new->conf.keyidx);
if (defbeaconkey && new)
__ieee80211_set_default_beacon_key(sdata,
new->conf.keyidx);
}
if (old)
......@@ -515,7 +548,9 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
struct ieee80211_key *key;
int i, j, err;
if (WARN_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS))
if (WARN_ON(idx < 0 ||
idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
NUM_DEFAULT_BEACON_KEYS))
return ERR_PTR(-EINVAL);
key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
......@@ -978,6 +1013,7 @@ static void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata,
sdata->crypto_tx_tailroom_pending_dec = 0;
ieee80211_debugfs_key_remove_mgmt_default(sdata);
ieee80211_debugfs_key_remove_beacon_default(sdata);
list_for_each_entry_safe(key, tmp, &sdata->key_list, list) {
ieee80211_key_replace(key->sdata, key->sta,
......
......@@ -17,6 +17,7 @@
#define NUM_DEFAULT_KEYS 4
#define NUM_DEFAULT_MGMT_KEYS 2
#define NUM_DEFAULT_BEACON_KEYS 2
#define INVALID_PTK_KEYIDX 2 /* Keyidx always pointing to a NULL key for PTK */
struct ieee80211_local;
......@@ -153,6 +154,8 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
bool uni, bool multi);
void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
int idx);
void ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata,
int idx);
void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata,
bool force_synchronize);
void ieee80211_free_sta_keys(struct ieee80211_local *local,
......
......@@ -589,8 +589,6 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_STA);
wiphy_ext_feature_set(wiphy,
NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211);
wiphy_ext_feature_set(wiphy,
NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_MAC_ADDRS);
if (!ops->hw_scan) {
wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
......
......@@ -983,7 +983,8 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb)
if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da))
return -1;
if (!ieee80211_is_robust_mgmt_frame(skb))
if (!ieee80211_is_robust_mgmt_frame(skb) &&
!ieee80211_is_beacon(hdr->frame_control))
return -1; /* not a robust management frame */
mmie = (struct ieee80211_mmie *)
......@@ -1868,6 +1869,41 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
return RX_CONTINUE;
} /* ieee80211_rx_h_sta_process */
static struct ieee80211_key *
ieee80211_rx_get_bigtk(struct ieee80211_rx_data *rx, int idx)
{
struct ieee80211_key *key = NULL;
struct ieee80211_sub_if_data *sdata = rx->sdata;
int idx2;
/* Make sure key gets set if either BIGTK key index is set so that
* ieee80211_drop_unencrypted_mgmt() can properly drop both unprotected
* Beacon frames and Beacon frames that claim to use another BIGTK key
* index (i.e., a key that we do not have).
*/
if (idx < 0) {
idx = NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS;
idx2 = idx + 1;
} else {
if (idx == NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
idx2 = idx + 1;
else
idx2 = idx - 1;
}
if (rx->sta)
key = rcu_dereference(rx->sta->gtk[idx]);
if (!key)
key = rcu_dereference(sdata->keys[idx]);
if (!key && rx->sta)
key = rcu_dereference(rx->sta->gtk[idx2]);
if (!key)
key = rcu_dereference(sdata->keys[idx2]);
return key;
}
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
{
......@@ -1885,17 +1921,18 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
/*
* Key selection 101
*
* There are four types of keys:
* There are five types of keys:
* - GTK (group keys)
* - IGTK (group keys for management frames)
* - BIGTK (group keys for Beacon frames)
* - PTK (pairwise keys)
* - STK (station-to-station pairwise keys)
*
* When selecting a key, we have to distinguish between multicast
* (including broadcast) and unicast frames, the latter can only
* use PTKs and STKs while the former always use GTKs and IGTKs.
* Unless, of course, actual WEP keys ("pre-RSNA") are used, then
* unicast frames can also use key indices like GTKs. Hence, if we
* use PTKs and STKs while the former always use GTKs, IGTKs, and
* BIGTKs. Unless, of course, actual WEP keys ("pre-RSNA") are used,
* then unicast frames can also use key indices like GTKs. Hence, if we
* don't have a PTK/STK we check the key index for a WEP key.
*
* Note that in a regular BSS, multicast frames are sent by the
......@@ -1939,6 +1976,20 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
/* Skip decryption if the frame is not protected. */
if (!ieee80211_has_protected(fc))
return RX_CONTINUE;
} else if (mmie_keyidx >= 0 && ieee80211_is_beacon(fc)) {
/* Broadcast/multicast robust management frame / BIP */
if ((status->flag & RX_FLAG_DECRYPTED) &&
(status->flag & RX_FLAG_IV_STRIPPED))
return RX_CONTINUE;
if (mmie_keyidx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS ||
mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
NUM_DEFAULT_BEACON_KEYS)
return RX_DROP_MONITOR; /* unexpected BIP keyidx */
rx->key = ieee80211_rx_get_bigtk(rx, mmie_keyidx);
if (!rx->key)
return RX_CONTINUE; /* Beacon protection not in use */
} else if (mmie_keyidx >= 0) {
/* Broadcast/multicast robust management frame / BIP */
if ((status->flag & RX_FLAG_DECRYPTED) &&
......@@ -1968,11 +2019,12 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
struct ieee80211_sub_if_data *sdata = rx->sdata;
int i;
if (ieee80211_is_mgmt(fc) &&
is_multicast_ether_addr(hdr->addr1) &&
(key = rcu_dereference(rx->sdata->default_mgmt_key)))
rx->key = key;
else {
if (ieee80211_is_beacon(fc)) {
key = ieee80211_rx_get_bigtk(rx, -1);
} else if (ieee80211_is_mgmt(fc) &&
is_multicast_ether_addr(hdr->addr1)) {
key = rcu_dereference(rx->sdata->default_mgmt_key);
} else {
if (rx->sta) {
for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
key = rcu_dereference(rx->sta->gtk[i]);
......@@ -1987,9 +2039,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
break;
}
}
if (key)
rx->key = key;
}
if (key)
rx->key = key;
return RX_CONTINUE;
} else {
/*
......@@ -2358,6 +2410,9 @@ static int ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
rx->skb->len);
return -EACCES;
}
if (unlikely(ieee80211_is_beacon(fc) && rx->key &&
ieee80211_get_mmie_keyidx(rx->skb) < 0))
return -EACCES;
/*
* When using MFP, Action frames are not allowed prior to
* having configured keys.
......
......@@ -201,8 +201,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
mgmt->bssid, cbss->bssid);
/* In case the signal is invalid update the status */
signal_valid = abs(channel->center_freq - cbss->channel->center_freq)
<= local->hw.wiphy->max_adj_channel_rssi_comp;
signal_valid = channel == cbss->channel;
if (!signal_valid)
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
......
......@@ -533,7 +533,9 @@ struct sta_info {
u8 addr[ETH_ALEN];
struct ieee80211_local *local;
struct ieee80211_sub_if_data *sdata;
struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS +
NUM_DEFAULT_MGMT_KEYS +
NUM_DEFAULT_BEACON_KEYS];
struct ieee80211_key __rcu *ptk[NUM_DEFAULT_KEYS];
u8 ptk_idx;
struct rate_control_ref *rate_ctrl;
......
......@@ -5,7 +5,7 @@
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2018 Intel Corporation
* Copyright (C) 2018-2020 Intel Corporation
*
* Transmit and frame generation functions.
*/
......@@ -3682,7 +3682,8 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
encap_out:
IEEE80211_SKB_CB(skb)->control.vif = vif;
if (wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
if (vif &&
wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
u32 airtime;
airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta,
......@@ -4663,6 +4664,28 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
}
EXPORT_SYMBOL(ieee80211_csa_is_complete);
static int ieee80211_beacon_protect(struct sk_buff *skb,
struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata)
{
ieee80211_tx_result res;
struct ieee80211_tx_data tx;
memset(&tx, 0, sizeof(tx));
tx.key = rcu_dereference(sdata->default_beacon_key);
if (!tx.key)
return 0;
tx.local = local;
tx.sdata = sdata;
__skb_queue_head_init(&tx.skbs);
__skb_queue_tail(&tx.skbs, skb);
res = ieee80211_tx_h_encrypt(&tx);
if (WARN_ON_ONCE(res != TX_CONTINUE))
return -1;
return 0;
}
static struct sk_buff *
__ieee80211_beacon_get(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
......@@ -4730,6 +4753,9 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
if (beacon->tail)
skb_put_data(skb, beacon->tail,
beacon->tail_len);
if (ieee80211_beacon_protect(skb, local, sdata) < 0)
goto out;
} else
goto out;
} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
......@@ -5282,8 +5308,7 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
const u8 *buf, size_t len,
const u8 *dest, const u8 *src, __be16 proto,
bool unencrypted)
const u8 *dest, __be16 proto, bool unencrypted)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
......@@ -5314,7 +5339,7 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
ehdr = skb_push(skb, sizeof(struct ethhdr));
memcpy(ehdr->h_dest, dest, ETH_ALEN);
memcpy(ehdr->h_source, src, ETH_ALEN);
memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN);
ehdr->h_proto = proto;
skb->dev = dev;
......
This diff is collapsed.
......@@ -136,6 +136,19 @@ rdev_set_default_mgmt_key(struct cfg80211_registered_device *rdev,
return ret;
}
static inline int
rdev_set_default_beacon_key(struct cfg80211_registered_device *rdev,
struct net_device *netdev, u8 key_index)
{
int ret;
trace_rdev_set_default_beacon_key(&rdev->wiphy, netdev, key_index);
ret = rdev->ops->set_default_beacon_key(&rdev->wiphy, netdev,
key_index);
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}
static inline int rdev_start_ap(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct cfg80211_ap_settings *settings)
......@@ -734,14 +747,14 @@ static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev,
static inline int rdev_tx_control_port(struct cfg80211_registered_device *rdev,
struct net_device *dev,
const void *buf, size_t len,
const u8 *dest, const u8 *src,
__be16 proto, const bool noencrypt)
const u8 *dest, __be16 proto,
const bool noencrypt)
{
int ret;
trace_rdev_tx_control_port(&rdev->wiphy, dev, buf, len,
dest, src, proto, noencrypt);
dest, proto, noencrypt);
ret = rdev->ops->tx_control_port(&rdev->wiphy, dev, buf, len,
dest, src, proto, noencrypt);
dest, proto, noencrypt);
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}
......@@ -1313,4 +1326,28 @@ rdev_probe_mesh_link(struct cfg80211_registered_device *rdev,
return ret;
}
static inline int rdev_set_tid_config(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct cfg80211_tid_config *tid_conf)
{
int ret;
trace_rdev_set_tid_config(&rdev->wiphy, dev, tid_conf);
ret = rdev->ops->set_tid_config(&rdev->wiphy, dev, tid_conf);
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}
static inline int rdev_reset_tid_config(struct cfg80211_registered_device *rdev,
struct net_device *dev, const u8 *peer,
u8 tids)
{
int ret;
trace_rdev_reset_tid_config(&rdev->wiphy, dev, peer, tids);
ret = rdev->ops->reset_tid_config(&rdev->wiphy, dev, peer, tids);
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}
#endif /* __CFG80211_RDEV_OPS */
......@@ -556,9 +556,8 @@ cfg80211_find_sched_scan_req(struct cfg80211_registered_device *rdev, u64 reqid)
{
struct cfg80211_sched_scan_request *pos;
WARN_ON_ONCE(!rcu_read_lock_held() && !lockdep_rtnl_is_held());
list_for_each_entry_rcu(pos, &rdev->sched_scan_req_list, list) {
list_for_each_entry_rcu(pos, &rdev->sched_scan_req_list, list,
lockdep_rtnl_is_held()) {
if (pos->reqid == reqid)
return pos;
}
......@@ -1434,8 +1433,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
}
rcu_assign_pointer(tmp.pub.ies, ies);
signal_valid = abs(data->chan->center_freq - channel->center_freq) <=
wiphy->max_adj_channel_rssi_comp;
signal_valid = data->chan == channel;
res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid, ts);
if (!res)
return NULL;
......@@ -1852,8 +1850,7 @@ cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
memcpy(tmp.pub.chain_signal, data->chain_signal, IEEE80211_MAX_CHAINS);
ether_addr_copy(tmp.parent_bssid, data->parent_bssid);
signal_valid = abs(data->chan->center_freq - channel->center_freq) <=
wiphy->max_adj_channel_rssi_comp;
signal_valid = data->chan == channel;
res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid,
jiffies);
if (!res)
......
......@@ -1111,9 +1111,16 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
* Delete all the keys ... pairwise keys can't really
* exist any more anyway, but default keys might.
*/
if (rdev->ops->del_key)
for (i = 0; i < 6; i++)
if (rdev->ops->del_key) {
int max_key_idx = 5;
if (wiphy_ext_feature_isset(
wdev->wiphy,
NL80211_EXT_FEATURE_BEACON_PROTECTION))
max_key_idx = 7;
for (i = 0; i <= max_key_idx; i++)
rdev_del_key(rdev, dev, i, false, NULL);
}
rdev_set_qos_map(rdev, dev, NULL);
......
......@@ -510,6 +510,23 @@ TRACE_EVENT(rdev_set_default_mgmt_key,
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index)
);
TRACE_EVENT(rdev_set_default_beacon_key,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index),
TP_ARGS(wiphy, netdev, key_index),
TP_STRUCT__entry(
WIPHY_ENTRY
NETDEV_ENTRY
__field(u8, key_index)
),
TP_fast_assign(
WIPHY_ASSIGN;
NETDEV_ASSIGN;
__entry->key_index = key_index;
),
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key index: %u",
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index)
);
TRACE_EVENT(rdev_start_ap,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
struct cfg80211_ap_settings *settings),
......@@ -1928,31 +1945,27 @@ TRACE_EVENT(rdev_mgmt_tx,
TRACE_EVENT(rdev_tx_control_port,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
const u8 *buf, size_t len,
const u8 *dest, const u8 *src, __be16 proto,
const u8 *buf, size_t len, const u8 *dest, __be16 proto,
bool unencrypted),
TP_ARGS(wiphy, netdev, buf, len, dest, src, proto, unencrypted),
TP_ARGS(wiphy, netdev, buf, len, dest, proto, unencrypted),
TP_STRUCT__entry(
WIPHY_ENTRY
NETDEV_ENTRY
MAC_ENTRY(dest)
MAC_ENTRY(src)
__field(u16, proto)
__field(__be16, proto)
__field(bool, unencrypted)
),
TP_fast_assign(
WIPHY_ASSIGN;
NETDEV_ASSIGN;
MAC_ASSIGN(dest, dest);
MAC_ASSIGN(src, src);
__entry->proto = be16_to_cpu(proto);
__entry->proto = proto;
__entry->unencrypted = unencrypted;
),
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", dest: " MAC_PR_FMT
", src: " MAC_PR_FMT ", proto: 0x%x, unencrypted: %s",
WIPHY_PR_ARG, NETDEV_PR_ARG,
MAC_PR_ARG(dest), MAC_PR_ARG(src),
__entry->proto,
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ","
" proto: 0x%x, unencrypted: %s",
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dest),
be16_to_cpu(__entry->proto),
BOOL_TO_STR(__entry->unencrypted))
);
......@@ -2844,7 +2857,6 @@ TRACE_EVENT(cfg80211_rx_control_port,
TP_STRUCT__entry(
NETDEV_ENTRY
__field(int, len)
MAC_ENTRY(to)
MAC_ENTRY(from)
__field(u16, proto)
__field(bool, unencrypted)
......@@ -2852,14 +2864,12 @@ TRACE_EVENT(cfg80211_rx_control_port,
TP_fast_assign(
NETDEV_ASSIGN;
__entry->len = skb->len;
MAC_ASSIGN(to, eth_hdr(skb)->h_dest);
MAC_ASSIGN(from, eth_hdr(skb)->h_source);
__entry->proto = be16_to_cpu(skb->protocol);
__entry->unencrypted = unencrypted;
),
TP_printk(NETDEV_PR_FMT ", len=%d, dest: " MAC_PR_FMT
", src: " MAC_PR_FMT ", proto: 0x%x, unencrypted: %s",
NETDEV_PR_ARG, __entry->len, MAC_PR_ARG(to), MAC_PR_ARG(from),
TP_printk(NETDEV_PR_FMT ", len=%d, " MAC_PR_FMT ", proto: 0x%x, unencrypted: %s",
NETDEV_PR_ARG, __entry->len, MAC_PR_ARG(from),
__entry->proto, BOOL_TO_STR(__entry->unencrypted))
);
......@@ -3470,6 +3480,43 @@ TRACE_EVENT(rdev_probe_mesh_link,
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dest))
);
TRACE_EVENT(rdev_set_tid_config,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
struct cfg80211_tid_config *tid_conf),
TP_ARGS(wiphy, netdev, tid_conf),
TP_STRUCT__entry(
WIPHY_ENTRY
NETDEV_ENTRY
MAC_ENTRY(peer)
),
TP_fast_assign(
WIPHY_ASSIGN;
NETDEV_ASSIGN;
MAC_ASSIGN(peer, tid_conf->peer);
),
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT,
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
);
TRACE_EVENT(rdev_reset_tid_config,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
const u8 *peer, u8 tids),
TP_ARGS(wiphy, netdev, peer, tids),
TP_STRUCT__entry(
WIPHY_ENTRY
NETDEV_ENTRY
MAC_ENTRY(peer)
__field(u8, tids)
),
TP_fast_assign(
WIPHY_ASSIGN;
NETDEV_ASSIGN;
MAC_ASSIGN(peer, peer);
__entry->tids = tids;
),
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT ", tids: 0x%x",
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->tids)
);
#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
#undef TRACE_INCLUDE_PATH
......
......@@ -231,7 +231,12 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
struct key_params *params, int key_idx,
bool pairwise, const u8 *mac_addr)
{
if (key_idx < 0 || key_idx > 5)
int max_key_idx = 5;
if (wiphy_ext_feature_isset(&rdev->wiphy,
NL80211_EXT_FEATURE_BEACON_PROTECTION))
max_key_idx = 7;
if (key_idx < 0 || key_idx > max_key_idx)
return -EINVAL;
if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment