Add external EAPOL transmission option for testing purposes
The new ext_eapol_frame_io parameter can be used to configure hostapd and wpa_supplicant to use control interface for receiving and transmitting EAPOL frames. This makes it easier to implement automated test cases for protocol testing. This functionality is included only in CONFIG_TESTING_OPTIONS=y builds. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
61fc90483f
commit
9d4ff04af3
8 changed files with 160 additions and 1 deletions
|
@ -1074,6 +1074,8 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
|
} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
|
||||||
hapd->ext_mgmt_frame_handling = atoi(value);
|
hapd->ext_mgmt_frame_handling = atoi(value);
|
||||||
|
} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
|
||||||
|
hapd->ext_eapol_frame_io = atoi(value);
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
} else {
|
} else {
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
|
@ -1249,6 +1251,44 @@ static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd)
|
||||||
|
{
|
||||||
|
char *pos;
|
||||||
|
u8 src[ETH_ALEN], *buf;
|
||||||
|
int used;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
|
||||||
|
|
||||||
|
pos = cmd;
|
||||||
|
used = hwaddr_aton2(pos, src);
|
||||||
|
if (used < 0)
|
||||||
|
return -1;
|
||||||
|
pos += used;
|
||||||
|
while (*pos == ' ')
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
len = os_strlen(pos);
|
||||||
|
if (len & 1)
|
||||||
|
return -1;
|
||||||
|
len /= 2;
|
||||||
|
|
||||||
|
buf = os_malloc(len);
|
||||||
|
if (buf == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (hexstr2bin(pos, buf, len) < 0) {
|
||||||
|
os_free(buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ieee802_1x_receive(hapd, src, buf, len);
|
||||||
|
os_free(buf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
|
|
||||||
|
@ -1551,6 +1591,9 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
|
||||||
} else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
|
} else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
|
||||||
if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
|
if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
|
} else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
|
||||||
|
if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0)
|
||||||
|
reply_len = -1;
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
|
} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
|
||||||
if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
|
if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
|
||||||
|
|
|
@ -247,7 +247,8 @@ struct hostapd_data {
|
||||||
#endif /* CONFIG_SAE */
|
#endif /* CONFIG_SAE */
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
int ext_mgmt_frame_handling;
|
unsigned int ext_mgmt_frame_handling:1;
|
||||||
|
unsigned int ext_eapol_frame_io:1;
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,20 @@ static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
|
|
||||||
if (wpa_auth_pairwise_set(sta->wpa_sm))
|
if (wpa_auth_pairwise_set(sta->wpa_sm))
|
||||||
encrypt = 1;
|
encrypt = 1;
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (hapd->ext_eapol_frame_io) {
|
||||||
|
size_t hex_len = 2 * len + 1;
|
||||||
|
char *hex = os_malloc(hex_len);
|
||||||
|
|
||||||
|
if (hex) {
|
||||||
|
wpa_snprintf_hex(hex, hex_len, buf, len);
|
||||||
|
wpa_msg(hapd->msg_ctx, MSG_INFO,
|
||||||
|
"EAPOL-TX " MACSTR " %s",
|
||||||
|
MAC2STR(sta->addr), hex);
|
||||||
|
os_free(hex);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
if (sta->flags & WLAN_STA_PREAUTH) {
|
if (sta->flags & WLAN_STA_PREAUTH) {
|
||||||
rsn_preauth_send(hapd, sta, buf, len);
|
rsn_preauth_send(hapd, sta, buf, len);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -299,6 +299,21 @@ static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr,
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
u32 flags = 0;
|
u32 flags = 0;
|
||||||
|
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (hapd->ext_eapol_frame_io) {
|
||||||
|
size_t hex_len = 2 * data_len + 1;
|
||||||
|
char *hex = os_malloc(hex_len);
|
||||||
|
|
||||||
|
if (hex == NULL)
|
||||||
|
return -1;
|
||||||
|
wpa_snprintf_hex(hex, hex_len, data, data_len);
|
||||||
|
wpa_msg(hapd->msg_ctx, MSG_INFO, "EAPOL-TX " MACSTR " %s",
|
||||||
|
MAC2STR(addr), hex);
|
||||||
|
os_free(hex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
sta = ap_get_sta(hapd, addr);
|
sta = ap_get_sta(hapd, addr);
|
||||||
if (sta)
|
if (sta)
|
||||||
flags = hostapd_sta_flags_to_drv(sta->flags);
|
flags = hostapd_sta_flags_to_drv(sta->flags);
|
||||||
|
@ -404,6 +419,21 @@ static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto,
|
||||||
struct l2_ethhdr *buf;
|
struct l2_ethhdr *buf;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (hapd->ext_eapol_frame_io && proto == ETH_P_EAPOL) {
|
||||||
|
size_t hex_len = 2 * data_len + 1;
|
||||||
|
char *hex = os_malloc(hex_len);
|
||||||
|
|
||||||
|
if (hex == NULL)
|
||||||
|
return -1;
|
||||||
|
wpa_snprintf_hex(hex, hex_len, data, data_len);
|
||||||
|
wpa_msg(hapd->msg_ctx, MSG_INFO, "EAPOL-TX " MACSTR " %s",
|
||||||
|
MAC2STR(dst), hex);
|
||||||
|
os_free(hex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211R
|
#ifdef CONFIG_IEEE80211R
|
||||||
if (proto == ETH_P_RRB && hapd->iface->interfaces &&
|
if (proto == ETH_P_RRB && hapd->iface->interfaces &&
|
||||||
hapd->iface->interfaces->for_each_interface) {
|
hapd->iface->interfaces->for_each_interface) {
|
||||||
|
|
|
@ -629,6 +629,10 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
hapd_iface->bss[i]->setup_complete_cb = wpas_ap_configured_cb;
|
hapd_iface->bss[i]->setup_complete_cb = wpas_ap_configured_cb;
|
||||||
hapd_iface->bss[i]->setup_complete_cb_ctx = wpa_s;
|
hapd_iface->bss[i]->setup_complete_cb_ctx = wpa_s;
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
hapd_iface->bss[i]->ext_eapol_frame_io =
|
||||||
|
wpa_s->ext_eapol_frame_io;
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
}
|
}
|
||||||
|
|
||||||
os_memcpy(hapd_iface->bss[0]->own_addr, wpa_s->own_addr, ETH_ALEN);
|
os_memcpy(hapd_iface->bss[0]->own_addr, wpa_s->own_addr, ETH_ALEN);
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "common/ieee802_11_defs.h"
|
#include "common/ieee802_11_defs.h"
|
||||||
#include "common/ieee802_11_common.h"
|
#include "common/ieee802_11_common.h"
|
||||||
#include "common/wpa_ctrl.h"
|
#include "common/wpa_ctrl.h"
|
||||||
|
#include "ap/hostapd.h"
|
||||||
#include "eap_peer/eap.h"
|
#include "eap_peer/eap.h"
|
||||||
#include "eapol_supp/eapol_supp_sm.h"
|
#include "eapol_supp/eapol_supp_sm.h"
|
||||||
#include "rsn_supp/wpa.h"
|
#include "rsn_supp/wpa.h"
|
||||||
|
@ -420,6 +421,14 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
|
} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
|
||||||
wpa_s->ext_mgmt_frame_handling = !!atoi(value);
|
wpa_s->ext_mgmt_frame_handling = !!atoi(value);
|
||||||
|
} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
|
||||||
|
wpa_s->ext_eapol_frame_io = !!atoi(value);
|
||||||
|
#ifdef CONFIG_AP
|
||||||
|
if (wpa_s->ap_iface) {
|
||||||
|
wpa_s->ap_iface->bss[0]->ext_eapol_frame_io =
|
||||||
|
wpa_s->ext_eapol_frame_io;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_AP */
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
#ifndef CONFIG_NO_CONFIG_BLOBS
|
#ifndef CONFIG_NO_CONFIG_BLOBS
|
||||||
} else if (os_strcmp(cmd, "blob") == 0) {
|
} else if (os_strcmp(cmd, "blob") == 0) {
|
||||||
|
@ -5794,6 +5803,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
|
||||||
#endif /* CONFIG_INTERWORKING */
|
#endif /* CONFIG_INTERWORKING */
|
||||||
|
|
||||||
wpa_s->ext_mgmt_frame_handling = 0;
|
wpa_s->ext_mgmt_frame_handling = 0;
|
||||||
|
wpa_s->ext_eapol_frame_io = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -6244,6 +6254,44 @@ static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd)
|
||||||
|
{
|
||||||
|
char *pos;
|
||||||
|
u8 src[ETH_ALEN], *buf;
|
||||||
|
int used;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
|
||||||
|
|
||||||
|
pos = cmd;
|
||||||
|
used = hwaddr_aton2(pos, src);
|
||||||
|
if (used < 0)
|
||||||
|
return -1;
|
||||||
|
pos += used;
|
||||||
|
while (*pos == ' ')
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
len = os_strlen(pos);
|
||||||
|
if (len & 1)
|
||||||
|
return -1;
|
||||||
|
len /= 2;
|
||||||
|
|
||||||
|
buf = os_malloc(len);
|
||||||
|
if (buf == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (hexstr2bin(pos, buf, len) < 0) {
|
||||||
|
os_free(buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_supplicant_rx_eapol(wpa_s, src, buf, len);
|
||||||
|
os_free(buf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
|
|
||||||
|
@ -7017,6 +7065,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
||||||
} else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) {
|
} else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) {
|
||||||
if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
|
if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
|
} else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
|
||||||
|
if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0)
|
||||||
|
reply_len = -1;
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
} else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
|
} else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
|
||||||
if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
|
if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
|
||||||
|
|
|
@ -844,6 +844,7 @@ struct wpa_supplicant {
|
||||||
|
|
||||||
unsigned int no_keep_alive:1;
|
unsigned int no_keep_alive:1;
|
||||||
unsigned int ext_mgmt_frame_handling:1;
|
unsigned int ext_mgmt_frame_handling:1;
|
||||||
|
unsigned int ext_eapol_frame_io:1;
|
||||||
|
|
||||||
#ifdef CONFIG_WNM
|
#ifdef CONFIG_WNM
|
||||||
u8 wnm_dialog_token;
|
u8 wnm_dialog_token;
|
||||||
|
|
|
@ -96,6 +96,21 @@ static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type,
|
||||||
static int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
|
static int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
|
||||||
u16 proto, const u8 *buf, size_t len)
|
u16 proto, const u8 *buf, size_t len)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (wpa_s->ext_eapol_frame_io && proto == ETH_P_EAPOL) {
|
||||||
|
size_t hex_len = 2 * len + 1;
|
||||||
|
char *hex = os_malloc(hex_len);
|
||||||
|
|
||||||
|
if (hex == NULL)
|
||||||
|
return -1;
|
||||||
|
wpa_snprintf_hex(hex, hex_len, buf, len);
|
||||||
|
wpa_msg(wpa_s, MSG_INFO, "EAPOL-TX " MACSTR " %s",
|
||||||
|
MAC2STR(dest), hex);
|
||||||
|
os_free(hex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
if (wpa_s->l2) {
|
if (wpa_s->l2) {
|
||||||
return l2_packet_send(wpa_s->l2, dest, proto, buf, len);
|
return l2_packet_send(wpa_s->l2, dest, proto, buf, len);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue