wpa_supplicant: Allow external management frame processing for testing
This enables more convenient protocol testing of AP and P2P functionality in various error cases and unexpected sequences without having to implement each test scenario within wpa_supplicant. ext_mgmt_frame_handle parameter can be set to 1 to move all management frame processing into an external program through control interface events (MGMT-RX and MGMT-TX-STATUS) and command (MGMT_TX). This is similar to the test interface that was added to hostapd previously, but allows more control on offchannel operations and more direct integration with the internal P2P module. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
5cf8801181
commit
60b893dfb3
3 changed files with 129 additions and 0 deletions
|
@ -40,6 +40,7 @@
|
|||
#include "blacklist.h"
|
||||
#include "autoscan.h"
|
||||
#include "wnm_sta.h"
|
||||
#include "offchannel.h"
|
||||
|
||||
static int wpa_supplicant_global_iface_list(struct wpa_global *global,
|
||||
char *buf, int len);
|
||||
|
@ -452,6 +453,10 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
|
|||
ret = set_disallow_aps(wpa_s, value);
|
||||
} else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
|
||||
wpa_s->no_keep_alive = !!atoi(value);
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
|
||||
wpa_s->ext_mgmt_frame_handling = !!atoi(value);
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
} else {
|
||||
value[-1] = '=';
|
||||
ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
|
||||
|
@ -5591,6 +5596,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
|
|||
#ifdef CONFIG_INTERWORKING
|
||||
hs20_cancel_fetch_osu(wpa_s);
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
wpa_s->ext_mgmt_frame_handling = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -5879,6 +5886,103 @@ static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
|
||||
static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s,
|
||||
unsigned int freq, const u8 *dst,
|
||||
const u8 *src, const u8 *bssid,
|
||||
const u8 *data, size_t data_len,
|
||||
enum offchannel_send_action_result
|
||||
result)
|
||||
{
|
||||
wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR
|
||||
" src=" MACSTR " bssid=" MACSTR " result=%s",
|
||||
freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
|
||||
result == OFFCHANNEL_SEND_ACTION_SUCCESS ?
|
||||
"SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ?
|
||||
"NO_ACK" : "FAILED"));
|
||||
}
|
||||
|
||||
|
||||
static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd)
|
||||
{
|
||||
char *pos, *param;
|
||||
size_t len;
|
||||
u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN];
|
||||
int res, used;
|
||||
int freq = 0, no_cck = 0, wait_time = 0;
|
||||
|
||||
/* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1]
|
||||
* <action=Action frame payload> */
|
||||
|
||||
wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
|
||||
|
||||
pos = cmd;
|
||||
used = hwaddr_aton2(pos, da);
|
||||
if (used < 0)
|
||||
return -1;
|
||||
pos += used;
|
||||
while (*pos == ' ')
|
||||
pos++;
|
||||
used = hwaddr_aton2(pos, bssid);
|
||||
if (used < 0)
|
||||
return -1;
|
||||
pos += used;
|
||||
|
||||
param = os_strstr(pos, " freq=");
|
||||
if (param) {
|
||||
param += 6;
|
||||
freq = atoi(param);
|
||||
}
|
||||
|
||||
param = os_strstr(pos, " no_cck=");
|
||||
if (param) {
|
||||
param += 8;
|
||||
no_cck = atoi(param);
|
||||
}
|
||||
|
||||
param = os_strstr(pos, " wait_time=");
|
||||
if (param) {
|
||||
param += 11;
|
||||
wait_time = atoi(param);
|
||||
}
|
||||
|
||||
param = os_strstr(pos, " action=");
|
||||
if (param == NULL)
|
||||
return -1;
|
||||
param += 8;
|
||||
|
||||
len = os_strlen(param);
|
||||
if (len & 1)
|
||||
return -1;
|
||||
len /= 2;
|
||||
|
||||
buf = os_malloc(len);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
if (hexstr2bin(param, buf, len) < 0) {
|
||||
os_free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid,
|
||||
buf, len, wait_time,
|
||||
wpas_ctrl_iface_mgmt_tx_cb, no_cck);
|
||||
os_free(buf);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting");
|
||||
offchannel_send_action_done(wpa_s);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
|
||||
char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
||||
char *buf, size_t *resp_len)
|
||||
{
|
||||
|
@ -6421,6 +6525,13 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
|||
} else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
|
||||
reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply,
|
||||
reply_size);
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
} else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
|
||||
if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0)
|
||||
reply_len = -1;
|
||||
} else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
|
||||
wpas_ctrl_iface_mgmt_tx_done(wpa_s);
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
} else {
|
||||
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
|
||||
reply_len = 16;
|
||||
|
|
|
@ -3137,6 +3137,23 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
|||
u16 fc, stype;
|
||||
const struct ieee80211_mgmt *mgmt;
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
if (wpa_s->ext_mgmt_frame_handling) {
|
||||
struct rx_mgmt *rx = &data->rx_mgmt;
|
||||
size_t hex_len = 2 * rx->frame_len + 1;
|
||||
char *hex = os_malloc(hex_len);
|
||||
if (hex) {
|
||||
wpa_snprintf_hex(hex, hex_len,
|
||||
rx->frame, rx->frame_len);
|
||||
wpa_msg(wpa_s, MSG_INFO, "MGMT-RX freq=%d datarate=%u ssi_signal=%d %s",
|
||||
rx->freq, rx->datarate, rx->ssi_signal,
|
||||
hex);
|
||||
os_free(hex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
mgmt = (const struct ieee80211_mgmt *)
|
||||
data->rx_mgmt.frame;
|
||||
fc = le_to_host16(mgmt->frame_control);
|
||||
|
|
|
@ -818,6 +818,7 @@ struct wpa_supplicant {
|
|||
u8 last_gas_dialog_token, prev_gas_dialog_token;
|
||||
|
||||
unsigned int no_keep_alive:1;
|
||||
unsigned int ext_mgmt_frame_handling:1;
|
||||
|
||||
#ifdef CONFIG_WNM
|
||||
u8 wnm_dialog_token;
|
||||
|
|
Loading…
Reference in a new issue