OCV: Allow OCI channel to be overridden for testing (AP)

Add hostapd configuration parameters oci_freq_override_* to allow the
OCI channel information to be overridden for various frames for testing
purposes. This can be set in the configuration and also updated during
the runtime of a BSS.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2020-05-30 00:04:53 +03:00 committed by Jouni Malinen
parent d10a57f6e9
commit 661e661186
9 changed files with 145 additions and 7 deletions

View file

@ -4217,6 +4217,20 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->skip_prune_assoc = atoi(pos); bss->skip_prune_assoc = atoi(pos);
} else if (os_strcmp(buf, "ft_rsnxe_used") == 0) { } else if (os_strcmp(buf, "ft_rsnxe_used") == 0) {
bss->ft_rsnxe_used = atoi(pos); bss->ft_rsnxe_used = atoi(pos);
} else if (os_strcmp(buf, "oci_freq_override_eapol_m3") == 0) {
bss->oci_freq_override_eapol_m3 = atoi(pos);
} else if (os_strcmp(buf, "oci_freq_override_eapol_g1") == 0) {
bss->oci_freq_override_eapol_g1 = atoi(pos);
} else if (os_strcmp(buf, "oci_freq_override_saquery_req") == 0) {
bss->oci_freq_override_saquery_req = atoi(pos);
} else if (os_strcmp(buf, "oci_freq_override_saquery_resp") == 0) {
bss->oci_freq_override_saquery_resp = atoi(pos);
} else if (os_strcmp(buf, "oci_freq_override_ft_assoc") == 0) {
bss->oci_freq_override_ft_assoc = atoi(pos);
} else if (os_strcmp(buf, "oci_freq_override_fils_assoc") == 0) {
bss->oci_freq_override_fils_assoc = atoi(pos);
} else if (os_strcmp(buf, "oci_freq_override_wnm_sleep") == 0) {
bss->oci_freq_override_wnm_sleep = atoi(pos);
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_SAE #ifdef CONFIG_SAE
} else if (os_strcmp(buf, "sae_password") == 0) { } else if (os_strcmp(buf, "sae_password") == 0) {

View file

@ -1484,6 +1484,22 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
if (os_strcmp(cmd, "ft_rsnxe_used") == 0) if (os_strcmp(cmd, "ft_rsnxe_used") == 0)
wpa_auth_set_ft_rsnxe_used(hapd->wpa_auth, wpa_auth_set_ft_rsnxe_used(hapd->wpa_auth,
hapd->conf->ft_rsnxe_used); hapd->conf->ft_rsnxe_used);
else if (os_strcmp(cmd, "oci_freq_override_eapol_m3") == 0)
wpa_auth_set_ocv_override_freq(
hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_EAPOL_M3,
atoi(value));
else if (os_strcmp(cmd, "oci_freq_override_eapol_g1") == 0)
wpa_auth_set_ocv_override_freq(
hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_EAPOL_G1,
atoi(value));
else if (os_strcmp(cmd, "oci_freq_override_ft_assoc") == 0)
wpa_auth_set_ocv_override_freq(
hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_FT_ASSOC,
atoi(value));
else if (os_strcmp(cmd, "oci_freq_override_fils_assoc") == 0)
wpa_auth_set_ocv_override_freq(
hapd->wpa_auth,
WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC, atoi(value));
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
} }

View file

@ -687,6 +687,13 @@ struct hostapd_bss_config {
int no_beacon_rsnxe; int no_beacon_rsnxe;
int skip_prune_assoc; int skip_prune_assoc;
int ft_rsnxe_used; int ft_rsnxe_used;
unsigned int oci_freq_override_eapol_m3;
unsigned int oci_freq_override_eapol_g1;
unsigned int oci_freq_override_saquery_req;
unsigned int oci_freq_override_saquery_resp;
unsigned int oci_freq_override_ft_assoc;
unsigned int oci_freq_override_fils_assoc;
unsigned int oci_freq_override_wnm_sleep;
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
#define MESH_ENABLED BIT(0) #define MESH_ENABLED BIT(0)

View file

@ -73,6 +73,16 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
"Failed to get channel info for OCI element in SA Query Request"); "Failed to get channel info for OCI element in SA Query Request");
return; return;
} }
#ifdef CONFIG_TESTING_OPTIONS
if (hapd->conf->oci_freq_override_saquery_req) {
wpa_printf(MSG_INFO,
"TEST: Override OCI frequency %d -> %u MHz",
ci.frequency,
hapd->conf->oci_freq_override_saquery_req);
ci.frequency =
hapd->conf->oci_freq_override_saquery_req;
}
#endif /* CONFIG_TESTING_OPTIONS */
oci_ie_len = OCV_OCI_EXTENDED_LEN; oci_ie_len = OCV_OCI_EXTENDED_LEN;
oci_ie = os_zalloc(oci_ie_len); oci_ie = os_zalloc(oci_ie_len);
@ -152,6 +162,16 @@ static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
"Failed to get channel info for OCI element in SA Query Response"); "Failed to get channel info for OCI element in SA Query Response");
return; return;
} }
#ifdef CONFIG_TESTING_OPTIONS
if (hapd->conf->oci_freq_override_saquery_resp) {
wpa_printf(MSG_INFO,
"TEST: Override OCI frequency %d -> %u MHz",
ci.frequency,
hapd->conf->oci_freq_override_saquery_resp);
ci.frequency =
hapd->conf->oci_freq_override_saquery_resp;
}
#endif /* CONFIG_TESTING_OPTIONS */
oci_ie_len = OCV_OCI_EXTENDED_LEN; oci_ie_len = OCV_OCI_EXTENDED_LEN;
oci_ie = os_zalloc(oci_ie_len); oci_ie = os_zalloc(oci_ie_len);

View file

@ -103,6 +103,15 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
os_free(wnmtfs_ie); os_free(wnmtfs_ie);
return -1; return -1;
} }
#ifdef CONFIG_TESTING_OPTIONS
if (hapd->conf->oci_freq_override_wnm_sleep) {
wpa_printf(MSG_INFO,
"TEST: Override OCI frequency %d -> %u MHz",
ci.frequency,
hapd->conf->oci_freq_override_wnm_sleep);
ci.frequency = hapd->conf->oci_freq_override_wnm_sleep;
}
#endif /* CONFIG_TESTING_OPTIONS */
oci_ie_len = OCV_OCI_EXTENDED_LEN; oci_ie_len = OCV_OCI_EXTENDED_LEN;
oci_ie = os_zalloc(oci_ie_len); oci_ie = os_zalloc(oci_ie_len);

View file

@ -2772,6 +2772,15 @@ static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm,
wpabuf_clear_free(plain); wpabuf_clear_free(plain);
return NULL; return NULL;
} }
#ifdef CONFIG_TESTING_OPTIONS
if (conf->oci_freq_override_fils_assoc) {
wpa_printf(MSG_INFO,
"TEST: Override OCI frequency %d -> %u MHz",
ci.frequency,
conf->oci_freq_override_fils_assoc);
ci.frequency = conf->oci_freq_override_fils_assoc;
}
#endif /* CONFIG_TESTING_OPTIONS */
pos = wpabuf_put(plain, OCV_OCI_EXTENDED_LEN); pos = wpabuf_put(plain, OCV_OCI_EXTENDED_LEN);
if (ocv_insert_extended_oci(&ci, pos) < 0) { if (ocv_insert_extended_oci(&ci, pos) < 0) {
@ -3237,7 +3246,9 @@ static int ocv_oci_len(struct wpa_state_machine *sm)
return 0; return 0;
} }
static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos)
static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos,
unsigned int freq)
{ {
#ifdef CONFIG_OCV #ifdef CONFIG_OCV
struct wpa_channel_info ci; struct wpa_channel_info ci;
@ -3250,6 +3261,14 @@ static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos)
"Failed to get channel info for OCI element"); "Failed to get channel info for OCI element");
return -1; return -1;
} }
#ifdef CONFIG_TESTING_OPTIONS
if (freq) {
wpa_printf(MSG_INFO,
"TEST: Override OCI KDE frequency %d -> %u MHz",
ci.frequency, freq);
ci.frequency = freq;
}
#endif /* CONFIG_TESTING_OPTIONS */
return ocv_insert_oci_kde(&ci, argpos); return ocv_insert_oci_kde(&ci, argpos);
#else /* CONFIG_OCV */ #else /* CONFIG_OCV */
@ -3466,7 +3485,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
gtk, gtk_len); gtk, gtk_len);
} }
pos = ieee80211w_kde_add(sm, pos); pos = ieee80211w_kde_add(sm, pos);
if (ocv_oci_add(sm, &pos) < 0) if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0)
goto done; goto done;
#ifdef CONFIG_IEEE80211R_AP #ifdef CONFIG_IEEE80211R_AP
@ -3816,7 +3835,8 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
gtk, gsm->GTK_len); gtk, gsm->GTK_len);
pos = ieee80211w_kde_add(sm, pos); pos = ieee80211w_kde_add(sm, pos);
if (ocv_oci_add(sm, &pos) < 0) { if (ocv_oci_add(sm, &pos,
conf->oci_freq_override_eapol_g1) < 0) {
os_free(kde_buf); os_free(kde_buf);
return; return;
} }
@ -5299,6 +5319,7 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm,
u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos; u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos;
u8 *opos; u8 *opos;
size_t gtk_len, kde_len; size_t gtk_len, kde_len;
struct wpa_auth_config *conf = &sm->wpa_auth->conf;
struct wpa_group *gsm = sm->group; struct wpa_group *gsm = sm->group;
u8 *wpa_ie; u8 *wpa_ie;
int wpa_ie_len, secure, gtkidx, encr = 0; int wpa_ie_len, secure, gtkidx, encr = 0;
@ -5409,7 +5430,7 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm,
opos += 2 + RSN_SELECTOR_LEN + 2; opos += 2 + RSN_SELECTOR_LEN + 2;
os_memset(opos, 0, 6); /* clear PN */ os_memset(opos, 0, 6); /* clear PN */
} }
if (ocv_oci_add(sm, &pos) < 0) { if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0) {
os_free(kde); os_free(kde);
return -1; return -1;
} }
@ -5417,9 +5438,7 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm,
#ifdef CONFIG_IEEE80211R_AP #ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
int res; int res;
struct wpa_auth_config *conf;
conf = &sm->wpa_auth->conf;
if (sm->assoc_resp_ftie && if (sm->assoc_resp_ftie &&
kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) { kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
os_memcpy(pos, sm->assoc_resp_ftie, os_memcpy(pos, sm->assoc_resp_ftie,
@ -5476,6 +5495,7 @@ int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
void *ctx1, void *ctx2) void *ctx1, void *ctx2)
{ {
u8 rsc[WPA_KEY_RSC_LEN]; u8 rsc[WPA_KEY_RSC_LEN];
struct wpa_auth_config *conf = &sm->wpa_auth->conf;
struct wpa_group *gsm = sm->group; struct wpa_group *gsm = sm->group;
const u8 *kde; const u8 *kde;
u8 *kde_buf = NULL, *pos, hdr[2]; u8 *kde_buf = NULL, *pos, hdr[2];
@ -5510,7 +5530,8 @@ int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
opos += 2 + RSN_SELECTOR_LEN + 2; opos += 2 + RSN_SELECTOR_LEN + 2;
os_memset(opos, 0, 6); /* clear PN */ os_memset(opos, 0, 6); /* clear PN */
} }
if (ocv_oci_add(sm, &pos) < 0) { if (ocv_oci_add(sm, &pos,
conf->oci_freq_override_eapol_g1) < 0) {
os_free(kde_buf); os_free(kde_buf);
return -1; return -1;
} }
@ -5552,4 +5573,27 @@ void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val)
wpa_auth->conf.ft_rsnxe_used = val; wpa_auth->conf.ft_rsnxe_used = val;
} }
void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth,
enum wpa_auth_ocv_override_frame frame,
unsigned int freq)
{
if (!wpa_auth)
return;
switch (frame) {
case WPA_AUTH_OCV_OVERRIDE_EAPOL_M3:
wpa_auth->conf.oci_freq_override_eapol_m3 = freq;
break;
case WPA_AUTH_OCV_OVERRIDE_EAPOL_G1:
wpa_auth->conf.oci_freq_override_eapol_g1 = freq;
break;
case WPA_AUTH_OCV_OVERRIDE_FT_ASSOC:
wpa_auth->conf.oci_freq_override_ft_assoc = freq;
break;
case WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC:
wpa_auth->conf.oci_freq_override_fils_assoc = freq;
break;
}
}
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */

View file

@ -241,6 +241,10 @@ struct wpa_auth_config {
unsigned int igtk_rsc_override_set:1; unsigned int igtk_rsc_override_set:1;
int ft_rsnxe_used; int ft_rsnxe_used;
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
unsigned int oci_freq_override_eapol_m3;
unsigned int oci_freq_override_eapol_g1;
unsigned int oci_freq_override_ft_assoc;
unsigned int oci_freq_override_fils_assoc;
#ifdef CONFIG_P2P #ifdef CONFIG_P2P
u8 ip_addr_go[4]; u8 ip_addr_go[4];
u8 ip_addr_mask[4]; u8 ip_addr_mask[4];
@ -526,4 +530,14 @@ int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth);
void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm); void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm);
void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val); void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val);
enum wpa_auth_ocv_override_frame {
WPA_AUTH_OCV_OVERRIDE_EAPOL_M3,
WPA_AUTH_OCV_OVERRIDE_EAPOL_G1,
WPA_AUTH_OCV_OVERRIDE_FT_ASSOC,
WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC,
};
void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth,
enum wpa_auth_ocv_override_frame frame,
unsigned int freq);
#endif /* WPA_AUTH_H */ #endif /* WPA_AUTH_H */

View file

@ -2661,6 +2661,15 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
os_free(subelem); os_free(subelem);
return NULL; return NULL;
} }
#ifdef CONFIG_TESTING_OPTIONS
if (conf->oci_freq_override_ft_assoc) {
wpa_printf(MSG_INFO,
"TEST: Override OCI frequency %d -> %u MHz",
ci.frequency,
conf->oci_freq_override_ft_assoc);
ci.frequency = conf->oci_freq_override_ft_assoc;
}
#endif /* CONFIG_TESTING_OPTIONS */
subelem_len += 2 + OCV_OCI_LEN; subelem_len += 2 + OCV_OCI_LEN;
nbuf = os_realloc(subelem, subelem_len); nbuf = os_realloc(subelem, subelem_len);

View file

@ -175,6 +175,11 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
wconf->igtk_rsc_override_set = 1; wconf->igtk_rsc_override_set = 1;
} }
wconf->ft_rsnxe_used = conf->ft_rsnxe_used; wconf->ft_rsnxe_used = conf->ft_rsnxe_used;
wconf->oci_freq_override_eapol_m3 = conf->oci_freq_override_eapol_m3;
wconf->oci_freq_override_eapol_g1 = conf->oci_freq_override_eapol_g1;
wconf->oci_freq_override_ft_assoc = conf->oci_freq_override_ft_assoc;
wconf->oci_freq_override_fils_assoc =
conf->oci_freq_override_fils_assoc;
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_P2P #ifdef CONFIG_P2P
os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4); os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4);