Add options in hostapd to inject connection failures.

Add hostapd_cli set commands for skip_send_eapol and enable_eapol_large_timeout.
1) with skip_send_eapol=1, AP won't send m0/m2 frames.
2) with enable_eapol_large_timeout=1, AP will time out 50 seconds after m0 or m2.
These two flags can also be set in hostapd.conf. By default, both are
set to 0.

With skip_send_eapol=1 and enable_eapol_large_timeout=0, AP will deauthenticate STA during 4-way handshake.
With skip_send_eapol=1 and enable_eapol_large_timeout=1, STA will hit auth timeout.

Bug: 174201865
Test: manual test with hostapd_cli set commands and check if STA hits
the above connection failures.

Change-Id: I3df1ab11a54b81254ce7efdd6c5e4d95a9314ddc
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index 3590b09..91cdefe 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -69,6 +69,10 @@
 endif
 endif
 
+ifdef CONFIG_TESTING_OPTIONS
+L_CFLAGS += -DCONFIG_TESTING_OPTIONS
+CONFIG_WPS_TESTING=y
+endif
 
 ifndef CONFIG_OS
 ifdef CONFIG_NATIVE_WINDOWS
diff --git a/hostapd/android.config b/hostapd/android.config
index f791daa..fd3c1a1 100644
--- a/hostapd/android.config
+++ b/hostapd/android.config
@@ -244,3 +244,11 @@
 # This can be used to enable functionality to improve interworking with
 # external networks.
 CONFIG_INTERWORKING=y
+
+# Testing options
+# This can be used to enable some testing options (see also the example
+# configuration file) that are useful for testing clients that
+# connect to this hostapd. These options allow, for example, to drop a
+# certain percentage of probe requests or auth/(re)assoc frames.
+# Each test case requires a flag set in hostapd.conf or through hostapd_cli
+#CONFIG_TESTING_OPTIONS=y
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index ce32f3c..efbfd80 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -4184,6 +4184,10 @@
 		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);
+	} else if (os_strcmp(buf, "skip_send_eapol") == 0) {
+		conf->skip_send_eapol = atoi(pos);
+	} else if (os_strcmp(buf, "enable_eapol_large_timeout") == 0) {
+		conf->enable_eapol_large_timeout = atoi(pos);
 #endif /* CONFIG_TESTING_OPTIONS */
 #ifdef CONFIG_SAE
 	} else if (os_strcmp(buf, "sae_password") == 0) {
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 30fa47f..02b41fd 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -1504,6 +1504,10 @@
 			wpa_auth_set_ocv_override_freq(
 				hapd->wpa_auth,
 				WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC, atoi(value));
+		else if (os_strcasecmp(cmd, "skip_send_eapol") == 0)
+			wpa_auth_set_skip_send_eapol(hapd->wpa_auth, atoi(value));
+		else if (os_strcasecmp(cmd, "enable_eapol_large_timeout") == 0)
+			wpa_auth_set_enable_eapol_large_timeout(hapd->wpa_auth, atoi(value));
 #endif /* CONFIG_TESTING_OPTIONS */
 	}
 
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 04535a1..f0e4236 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -252,6 +252,8 @@
 	conf->ignore_reassoc_probability = 0.0;
 	conf->corrupt_gtk_rekey_mic_probability = 0.0;
 	conf->ecsa_ie_only = 0;
+	conf->skip_send_eapol = 0;
+	conf->enable_eapol_large_timeout = 0;
 #endif /* CONFIG_TESTING_OPTIONS */
 
 	conf->acs = 0;
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index bada04c..0cb4b52 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -1005,6 +1005,8 @@
 	double ignore_reassoc_probability;
 	double corrupt_gtk_rekey_mic_probability;
 	int ecsa_ie_only;
+	unsigned int skip_send_eapol;
+	unsigned int enable_eapol_large_timeout;
 #endif /* CONFIG_TESTING_OPTIONS */
 
 #ifdef CONFIG_ACS
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 9d74bfc..e48894f 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -188,6 +188,10 @@
 {
 	if (!wpa_auth->cb->send_eapol)
 		return -1;
+#ifdef CONFIG_TESTING_OPTIONS
+	if (wpa_auth->conf.skip_send_eapol)
+		return 0;
+#endif
 	return wpa_auth->cb->send_eapol(wpa_auth->cb_ctx, addr, data, data_len,
 					encrypt);
 }
@@ -1663,7 +1667,7 @@
 
 	wpa_auth_set_eapol(wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 1);
 	wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len,
-			    sm->pairwise_set);
+			sm->pairwise_set);
 	os_free(hdr);
 }
 
@@ -1698,6 +1702,11 @@
 #ifdef TEST_FUZZ
 	timeout_ms = 1;
 #endif /* TEST_FUZZ */
+#ifdef CONFIG_TESTING_OPTIONS
+	if(wpa_auth->conf.enable_eapol_large_timeout) {
+		timeout_ms = 50 * 1000;
+	}
+#endif
 	wpa_printf(MSG_DEBUG,
 		   "WPA: Use EAPOL-Key timeout of %u ms (retry counter %u)",
 		   timeout_ms, ctr);
@@ -5612,4 +5621,19 @@
 	}
 }
 
+void wpa_auth_set_skip_send_eapol(struct wpa_authenticator *wpa_auth,
+				     u8 val)
+{
+	if (wpa_auth)
+		wpa_auth->conf.skip_send_eapol = val;
+}
+
+void wpa_auth_set_enable_eapol_large_timeout(struct wpa_authenticator *wpa_auth,
+				     u8 val)
+{
+	if (wpa_auth)
+		wpa_auth->conf.enable_eapol_large_timeout = val;
+}
+
+
 #endif /* CONFIG_TESTING_OPTIONS */
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 5f9df9c..ff90464 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -240,6 +240,8 @@
 	unsigned int gtk_rsc_override_set:1;
 	unsigned int igtk_rsc_override_set:1;
 	int ft_rsnxe_used;
+	unsigned int skip_send_eapol:1;
+	unsigned int enable_eapol_large_timeout:1;
 #endif /* CONFIG_TESTING_OPTIONS */
 	unsigned int oci_freq_override_eapol_m3;
 	unsigned int oci_freq_override_eapol_g1;
@@ -542,5 +544,9 @@
 void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth,
 				    enum wpa_auth_ocv_override_frame frame,
 				    unsigned int freq);
+void wpa_auth_set_skip_send_eapol(struct wpa_authenticator *wpa_auth,
+				     u8 val);
+void wpa_auth_set_enable_eapol_large_timeout(struct wpa_authenticator *wpa_auth,
+				     u8 val);
 
 #endif /* WPA_AUTH_H */
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index c01654f..bb44c7a 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -180,6 +180,8 @@
 	wconf->oci_freq_override_ft_assoc = conf->oci_freq_override_ft_assoc;
 	wconf->oci_freq_override_fils_assoc =
 		conf->oci_freq_override_fils_assoc;
+	wconf->skip_send_eapol = iconf->skip_send_eapol;
+	wconf->enable_eapol_large_timeout = iconf->enable_eapol_large_timeout;
 #endif /* CONFIG_TESTING_OPTIONS */
 #ifdef CONFIG_P2P
 	os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4);