hwsim: allow specific radio iftypes/ciphers

mac80211_hwsim now allows setting supported iftypes/ciphers. This patch
enables this support in hwsim. Specific iftypes/ciphers can now be
disabled via the command line when creating a radio:

Disable iftypes:
--iftype-disable station,ap,adhoc,p2p_client,p2p_go,mesh_point

Disable cipher types:
--cipher-disable ccmp,tkip,wep
This commit is contained in:
James Prestwood 2019-05-13 14:29:22 -07:00 committed by Denis Kenzior
parent 79dd04c13a
commit 0e31b33631
1 changed files with 129 additions and 1 deletions

View File

@ -41,6 +41,7 @@
#include "src/util.h"
#include "src/storage.h"
#include "src/mpdu.h"
#include "src/crypto.h"
#define HWSIM_SERVICE "net.connman.hwsim"
@ -86,10 +87,25 @@ enum {
HWSIM_ATTR_PAD,
HWSIM_ATTR_TX_INFO_FLAGS,
HWSIM_ATTR_PERM_ADDR,
HWSIM_ATTR_IFTYPE_SUPPORT,
HWSIM_ATTR_CIPHER_SUPPORT,
__HWSIM_ATTR_MAX,
};
#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
/*
* Should be kept in sync with HWSIM_IFTYPE_SUPPORT_MASK in mac80211_hwsim
*/
#define HWSIM_DEFAULT_IFTYPES \
( \
(1 << NL80211_IFTYPE_STATION) | \
(1 << NL80211_IFTYPE_AP) | \
(1 << NL80211_IFTYPE_P2P_CLIENT) | \
(1 << NL80211_IFTYPE_P2P_GO) | \
(1 << NL80211_IFTYPE_ADHOC) | \
(1 << NL80211_IFTYPE_MESH_POINT) \
)
enum hwsim_tx_control_flags {
HWSIM_TX_CTL_REQ_TX_STATUS = 1 << 0,
HWSIM_TX_CTL_NO_ACK = 1 << 1,
@ -111,6 +127,11 @@ struct hwsim_rule {
int signal;
};
struct hwsim_support {
const char *name;
uint32_t value;
};
static struct l_genl *genl;
static struct l_genl_family *hwsim;
static struct l_genl_family *nl80211;
@ -133,6 +154,37 @@ static struct l_dbus *dbus;
static struct l_queue *rules;
static unsigned int next_rule_id;
static uint32_t hwsim_iftypes = HWSIM_DEFAULT_IFTYPES;
static const uint32_t hwsim_supported_ciphers[] = {
CRYPTO_CIPHER_WEP40,
CRYPTO_CIPHER_WEP104,
CRYPTO_CIPHER_TKIP,
CRYPTO_CIPHER_CCMP,
CRYPTO_CIPHER_BIP,
};
static uint32_t hwsim_ciphers[L_ARRAY_SIZE(hwsim_supported_ciphers)];
static int hwsim_num_ciphers = 0;
/* list of disableable iftypes */
static const struct hwsim_support iftype_map[] = {
{ "station", 1 << NL80211_IFTYPE_STATION },
{ "ap", 1 << NL80211_IFTYPE_AP },
{ "adhoc", 1 << NL80211_IFTYPE_ADHOC },
{ "p2p_client", 1 << NL80211_IFTYPE_P2P_CLIENT },
{ "p2p_go", 1 << NL80211_IFTYPE_P2P_GO },
{ "mesh_point", 1 << NL80211_IFTYPE_MESH_POINT },
{ }
};
static const struct hwsim_support cipher_map[] = {
{ "wep40", CRYPTO_CIPHER_WEP40 },
{ "wep104", CRYPTO_CIPHER_WEP104 },
{ "tkip", CRYPTO_CIPHER_TKIP },
{ "ccmp", CRYPTO_CIPHER_CCMP },
{ "bip", CRYPTO_CIPHER_BIP },
{ }
};
static void do_debug(const char *str, void *user_data)
{
const char *prefix = user_data;
@ -2347,6 +2399,15 @@ static void hwsim_ready(void *user_data)
HWSIM_ATTR_SUPPORT_P2P_DEVICE,
0, NULL);
if (hwsim_iftypes != HWSIM_DEFAULT_IFTYPES)
l_genl_msg_append_attr(msg, HWSIM_ATTR_IFTYPE_SUPPORT,
4, &hwsim_iftypes);
if (hwsim_num_ciphers)
l_genl_msg_append_attr(msg, HWSIM_ATTR_CIPHER_SUPPORT,
sizeof(uint32_t) * hwsim_num_ciphers,
hwsim_ciphers);
l_genl_family_send(hwsim, msg, create_callback, NULL, NULL);
break;
@ -2389,6 +2450,62 @@ error:
l_main_quit();
}
static void hwsim_disable_support(char *disable,
const struct hwsim_support *map, uint32_t *mask)
{
char **list = l_strsplit(disable, ',');
char **iter = list;
int i;
while (*iter) {
for (i = 0; map[i].name; i++) {
if (!strcmp(map[i].name, *iter))
*mask &= ~(map[i].value);
}
iter++;
}
l_strfreev(list);
}
static bool is_cipher_disabled(char *args, enum crypto_cipher cipher)
{
char **list = l_strsplit(args, ',');
char **iter = list;
int i;
while (*iter) {
for (i = 0; cipher_map[i].name; i++) {
if (!strcmp(*iter, cipher_map[i].name) &&
cipher == cipher_map[i].value) {
printf("disable cipher: %s\n", cipher_map[i].name);
l_strfreev(list);
return true;
}
}
iter++;
}
l_strfreev(list);
return false;
}
static void hwsim_disable_ciphers(char *disable)
{
uint8_t i;
for (i = 0; i < L_ARRAY_SIZE(hwsim_supported_ciphers); i++) {
if (is_cipher_disabled(disable, hwsim_supported_ciphers[i]))
continue;
hwsim_ciphers[hwsim_num_ciphers] = hwsim_supported_ciphers[i];
hwsim_num_ciphers++;
}
}
static void hwsim_disappeared(void *user_data)
{
l_main_quit();
@ -2416,6 +2533,8 @@ static void usage(void)
"\t-n, --name <name> Name of a radio to be created\n"
"\t-i, --nointerface Do not create VIF\n"
"\t-p, --p2p Support P2P\n"
"\t-t, --iftype-disable List of disabled iftypes\n"
"\t-c, --cipher-disable List of disabled ciphers\n"
"\t-h, --help Show help options\n");
}
@ -2427,6 +2546,8 @@ static const struct option main_options[] = {
{ "nointerface", no_argument, NULL, 'i' },
{ "p2p", no_argument, NULL, 'p' },
{ "version", no_argument, NULL, 'v' },
{ "iftype-disable", required_argument, NULL, 't' },
{ "cipher-disable", required_argument, NULL, 'c' },
{ "help", no_argument, NULL, 'h' },
{ }
};
@ -2438,7 +2559,7 @@ int main(int argc, char *argv[])
for (;;) {
int opt;
opt = getopt_long(argc, argv, ":L:CD:kn:ipvh", main_options,
opt = getopt_long(argc, argv, ":L:CD:kndetc:ipvh", main_options,
NULL);
if (opt < 0)
break;
@ -2477,6 +2598,13 @@ int main(int argc, char *argv[])
case 'p':
p2p_attr = true;
break;
case 't':
hwsim_disable_support(optarg, iftype_map,
&hwsim_iftypes);
break;
case 'c':
hwsim_disable_ciphers(optarg);
break;
case 'v':
printf("%s\n", VERSION);
return EXIT_SUCCESS;