+
+static void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_data;
+ wpa_printf(MSG_DEBUG, "WPS: AP PIN timed out");
+ wpas_wps_ap_pin_disable(wpa_s);
+}
+
+
+static void wpas_wps_ap_pin_enable(struct wpa_supplicant *wpa_s, int timeout)
+{
+ struct hostapd_data *hapd;
+
+ if (wpa_s->ap_iface == NULL)
+ return;
+ hapd = wpa_s->ap_iface->bss[0];
+ wpa_printf(MSG_DEBUG, "WPS: Enabling AP PIN (timeout=%d)", timeout);
+ hapd->ap_pin_failures = 0;
+ eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL);
+ if (timeout > 0)
+ eloop_register_timeout(timeout, 0,
+ wpas_wps_ap_pin_timeout, wpa_s, NULL);
+}
+
+
+void wpas_wps_ap_pin_disable(struct wpa_supplicant *wpa_s)
+{
+ struct hostapd_data *hapd;
+
+ if (wpa_s->ap_iface == NULL)
+ return;
+ wpa_printf(MSG_DEBUG, "WPS: Disabling AP PIN");
+ hapd = wpa_s->ap_iface->bss[0];
+ os_free(hapd->conf->ap_pin);
+ hapd->conf->ap_pin = NULL;
+ eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL);
+}
+
+
+const char * wpas_wps_ap_pin_random(struct wpa_supplicant *wpa_s, int timeout)
+{
+ struct hostapd_data *hapd;
+ unsigned int pin;
+ char pin_txt[9];
+
+ if (wpa_s->ap_iface == NULL)
+ return NULL;
+ hapd = wpa_s->ap_iface->bss[0];
+ pin = wps_generate_pin();
+ os_snprintf(pin_txt, sizeof(pin_txt), "%08u", pin);
+ os_free(hapd->conf->ap_pin);
+ hapd->conf->ap_pin = os_strdup(pin_txt);
+ if (hapd->conf->ap_pin == NULL)
+ return NULL;
+ wpas_wps_ap_pin_enable(wpa_s, timeout);
+
+ return hapd->conf->ap_pin;
+}
+
+
+const char * wpas_wps_ap_pin_get(struct wpa_supplicant *wpa_s)
+{
+ struct hostapd_data *hapd;
+ if (wpa_s->ap_iface == NULL)
+ return NULL;
+ hapd = wpa_s->ap_iface->bss[0];
+ return hapd->conf->ap_pin;
+}
+
+
+int wpas_wps_ap_pin_set(struct wpa_supplicant *wpa_s, const char *pin,
+ int timeout)
+{
+ struct hostapd_data *hapd;
+ char pin_txt[9];
+ int ret;
+
+ if (wpa_s->ap_iface == NULL)
+ return -1;
+ hapd = wpa_s->ap_iface->bss[0];
+ ret = os_snprintf(pin_txt, sizeof(pin_txt), "%s", pin);
+ if (os_snprintf_error(sizeof(pin_txt), ret))
+ return -1;
+ os_free(hapd->conf->ap_pin);
+ hapd->conf->ap_pin = os_strdup(pin_txt);
+ if (hapd->conf->ap_pin == NULL)
+ return -1;
+ wpas_wps_ap_pin_enable(wpa_s, timeout);
+
+ return 0;
+}
+
+
+void wpa_supplicant_ap_pwd_auth_fail(struct wpa_supplicant *wpa_s)
+{
+ struct hostapd_data *hapd;
+
+ if (wpa_s->ap_iface == NULL)
+ return;
+ hapd = wpa_s->ap_iface->bss[0];
+
+ /*
+ * Registrar failed to prove its knowledge of the AP PIN. Disable AP
+ * PIN if this happens multiple times to slow down brute force attacks.
+ */
+ hapd->ap_pin_failures++;
+ wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u",
+ hapd->ap_pin_failures);
+ if (hapd->ap_pin_failures < 3)
+ return;
+
+ wpa_printf(MSG_DEBUG, "WPS: Disable AP PIN");
+ hapd->ap_pin_failures = 0;
+ os_free(hapd->conf->ap_pin);
+ hapd->conf->ap_pin = NULL;
+}
+
+
+#ifdef CONFIG_WPS_NFC
+
+struct wpabuf * wpas_ap_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
+ int ndef)
+{
+ struct hostapd_data *hapd;
+
+ if (wpa_s->ap_iface == NULL)
+ return NULL;
+ hapd = wpa_s->ap_iface->bss[0];
+ return hostapd_wps_nfc_config_token(hapd, ndef);
+}
+
+
+struct wpabuf * wpas_ap_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
+ int ndef)
+{
+ struct hostapd_data *hapd;
+
+ if (wpa_s->ap_iface == NULL)
+ return NULL;
+ hapd = wpa_s->ap_iface->bss[0];
+ return hostapd_wps_nfc_hs_cr(hapd, ndef);
+}
+
+
+int wpas_ap_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
+ const struct wpabuf *req,
+ const struct wpabuf *sel)
+{
+ struct hostapd_data *hapd;
+
+ if (wpa_s->ap_iface == NULL)
+ return -1;
+ hapd = wpa_s->ap_iface->bss[0];
+ return hostapd_wps_nfc_report_handover(hapd, req, sel);
+}
+
+#endif /* CONFIG_WPS_NFC */
+