mac80211_hwsim: allow configurable cipher types
The mac80211_hwsim driver does not specify supported cipher types, which in turn enables all ciphers to be supported in software. (see net/mac80211/main.c:ieee80211_init_cipher_suites). Allowing ciphers to be configurable is valuable for simulating older drivers that may not support all ciphers. This patch adds a new attribute: - HWSIM_ATTR_CIPHER_SUPPORT A u32 array/list of supported cipher types This only allows enabling/disabling cipher types listed in the (new) "hwsim_ciphers" array in mac80211_hwsim.c. Any unknown cipher type will result in -EINVAL. Signed-off-by: James Prestwood <james.prestwood@linux.intel.com> [fix some indentation, change to hwsim_known_ciphers(), add error messages, validate length better] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
99e3a44bac
commit
c0a0189d82
|
@ -374,6 +374,20 @@ static const struct ieee80211_rate hwsim_rates[] = {
|
||||||
{ .bitrate = 540 }
|
{ .bitrate = 540 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const u32 hwsim_ciphers[] = {
|
||||||
|
WLAN_CIPHER_SUITE_WEP40,
|
||||||
|
WLAN_CIPHER_SUITE_WEP104,
|
||||||
|
WLAN_CIPHER_SUITE_TKIP,
|
||||||
|
WLAN_CIPHER_SUITE_CCMP,
|
||||||
|
WLAN_CIPHER_SUITE_CCMP_256,
|
||||||
|
WLAN_CIPHER_SUITE_GCMP,
|
||||||
|
WLAN_CIPHER_SUITE_GCMP_256,
|
||||||
|
WLAN_CIPHER_SUITE_AES_CMAC,
|
||||||
|
WLAN_CIPHER_SUITE_BIP_CMAC_256,
|
||||||
|
WLAN_CIPHER_SUITE_BIP_GMAC_128,
|
||||||
|
WLAN_CIPHER_SUITE_BIP_GMAC_256,
|
||||||
|
};
|
||||||
|
|
||||||
#define OUI_QCA 0x001374
|
#define OUI_QCA 0x001374
|
||||||
#define QCA_NL80211_SUBCMD_TEST 1
|
#define QCA_NL80211_SUBCMD_TEST 1
|
||||||
enum qca_nl80211_vendor_subcmds {
|
enum qca_nl80211_vendor_subcmds {
|
||||||
|
@ -476,6 +490,8 @@ struct mac80211_hwsim_data {
|
||||||
struct ieee80211_iface_limit if_limits[3];
|
struct ieee80211_iface_limit if_limits[3];
|
||||||
int n_if_limits;
|
int n_if_limits;
|
||||||
|
|
||||||
|
u32 ciphers[ARRAY_SIZE(hwsim_ciphers)];
|
||||||
|
|
||||||
struct mac_address addresses[2];
|
struct mac_address addresses[2];
|
||||||
int channels, idx;
|
int channels, idx;
|
||||||
bool use_chanctx;
|
bool use_chanctx;
|
||||||
|
@ -603,6 +619,7 @@ static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
|
||||||
[HWSIM_ATTR_FREQ] = { .type = NLA_U32 },
|
[HWSIM_ATTR_FREQ] = { .type = NLA_U32 },
|
||||||
[HWSIM_ATTR_PERM_ADDR] = { .type = NLA_UNSPEC, .len = ETH_ALEN },
|
[HWSIM_ATTR_PERM_ADDR] = { .type = NLA_UNSPEC, .len = ETH_ALEN },
|
||||||
[HWSIM_ATTR_IFTYPE_SUPPORT] = { .type = NLA_U32 },
|
[HWSIM_ATTR_IFTYPE_SUPPORT] = { .type = NLA_U32 },
|
||||||
|
[HWSIM_ATTR_CIPHER_SUPPORT] = { .type = NLA_BINARY },
|
||||||
};
|
};
|
||||||
|
|
||||||
static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
|
static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
|
||||||
|
@ -2376,6 +2393,8 @@ struct hwsim_new_radio_params {
|
||||||
bool no_vif;
|
bool no_vif;
|
||||||
const u8 *perm_addr;
|
const u8 *perm_addr;
|
||||||
u32 iftypes;
|
u32 iftypes;
|
||||||
|
u32 *ciphers;
|
||||||
|
u8 n_ciphers;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb,
|
static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb,
|
||||||
|
@ -2748,6 +2767,13 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
|
||||||
hw->wiphy->iface_combinations = &data->if_combination;
|
hw->wiphy->iface_combinations = &data->if_combination;
|
||||||
hw->wiphy->n_iface_combinations = 1;
|
hw->wiphy->n_iface_combinations = 1;
|
||||||
|
|
||||||
|
if (param->ciphers) {
|
||||||
|
memcpy(data->ciphers, param->ciphers,
|
||||||
|
param->n_ciphers * sizeof(u32));
|
||||||
|
hw->wiphy->cipher_suites = data->ciphers;
|
||||||
|
hw->wiphy->n_cipher_suites = param->n_ciphers;
|
||||||
|
}
|
||||||
|
|
||||||
INIT_DELAYED_WORK(&data->roc_start, hw_roc_start);
|
INIT_DELAYED_WORK(&data->roc_start, hw_roc_start);
|
||||||
INIT_DELAYED_WORK(&data->roc_done, hw_roc_done);
|
INIT_DELAYED_WORK(&data->roc_done, hw_roc_done);
|
||||||
INIT_DELAYED_WORK(&data->hw_scan, hw_scan_work);
|
INIT_DELAYED_WORK(&data->hw_scan, hw_scan_work);
|
||||||
|
@ -3296,6 +3322,29 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ensures ciphers only include ciphers listed in 'hwsim_ciphers' array */
|
||||||
|
static bool hwsim_known_ciphers(const u32 *ciphers, int n_ciphers)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < n_ciphers; i++) {
|
||||||
|
int j;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
for (j = 0; j < ARRAY_SIZE(hwsim_ciphers); j++) {
|
||||||
|
if (ciphers[i] == hwsim_ciphers[j]) {
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
|
static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
|
||||||
{
|
{
|
||||||
struct hwsim_new_radio_params param = { 0 };
|
struct hwsim_new_radio_params param = { 0 };
|
||||||
|
@ -3377,6 +3426,36 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
|
||||||
param.p2p_device = true;
|
param.p2p_device = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (info->attrs[HWSIM_ATTR_CIPHER_SUPPORT]) {
|
||||||
|
u32 len = nla_len(info->attrs[HWSIM_ATTR_CIPHER_SUPPORT]);
|
||||||
|
|
||||||
|
param.ciphers =
|
||||||
|
nla_data(info->attrs[HWSIM_ATTR_CIPHER_SUPPORT]);
|
||||||
|
|
||||||
|
if (len % sizeof(u32)) {
|
||||||
|
NL_SET_ERR_MSG_ATTR(info->extack,
|
||||||
|
info->attrs[HWSIM_ATTR_CIPHER_SUPPORT],
|
||||||
|
"bad cipher list length");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
param.n_ciphers = len / sizeof(u32);
|
||||||
|
|
||||||
|
if (param.n_ciphers > ARRAY_SIZE(hwsim_ciphers)) {
|
||||||
|
NL_SET_ERR_MSG_ATTR(info->extack,
|
||||||
|
info->attrs[HWSIM_ATTR_CIPHER_SUPPORT],
|
||||||
|
"too many ciphers specified");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hwsim_known_ciphers(param.ciphers, param.n_ciphers)) {
|
||||||
|
NL_SET_ERR_MSG_ATTR(info->extack,
|
||||||
|
info->attrs[HWSIM_ATTR_CIPHER_SUPPORT],
|
||||||
|
"unsupported ciphers specified");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (info->attrs[HWSIM_ATTR_RADIO_NAME]) {
|
if (info->attrs[HWSIM_ATTR_RADIO_NAME]) {
|
||||||
hwname = kasprintf(GFP_KERNEL, "%.*s",
|
hwname = kasprintf(GFP_KERNEL, "%.*s",
|
||||||
nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]),
|
nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]),
|
||||||
|
|
|
@ -133,6 +133,7 @@ enum {
|
||||||
* rates of %HWSIM_ATTR_TX_INFO
|
* rates of %HWSIM_ATTR_TX_INFO
|
||||||
* @HWSIM_ATTR_PERM_ADDR: permanent mac address of new radio
|
* @HWSIM_ATTR_PERM_ADDR: permanent mac address of new radio
|
||||||
* @HWSIM_ATTR_IFTYPE_SUPPORT: u32 attribute of supported interface types bits
|
* @HWSIM_ATTR_IFTYPE_SUPPORT: u32 attribute of supported interface types bits
|
||||||
|
* @HWSIM_ATTR_CIPHER_SUPPORT: u32 array of supported cipher types
|
||||||
* @__HWSIM_ATTR_MAX: enum limit
|
* @__HWSIM_ATTR_MAX: enum limit
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -162,6 +163,7 @@ enum {
|
||||||
HWSIM_ATTR_TX_INFO_FLAGS,
|
HWSIM_ATTR_TX_INFO_FLAGS,
|
||||||
HWSIM_ATTR_PERM_ADDR,
|
HWSIM_ATTR_PERM_ADDR,
|
||||||
HWSIM_ATTR_IFTYPE_SUPPORT,
|
HWSIM_ATTR_IFTYPE_SUPPORT,
|
||||||
|
HWSIM_ATTR_CIPHER_SUPPORT,
|
||||||
__HWSIM_ATTR_MAX,
|
__HWSIM_ATTR_MAX,
|
||||||
};
|
};
|
||||||
#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
|
#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
|
||||||
|
|
Loading…
Reference in New Issue