From 95fb2db2420d8fa291fd6423cc6dbcd042f4eb46 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 6 Jan 2014 17:56:50 +0200 Subject: [PATCH] P2P: Reject group formation on WPS provisioning failure There is no need to wait for the 15 second group formation timeout to clear the state if WPS failure is detected during P2P group formation. Allow the WPS exchange steps (WSC_NACK and EAP-Failure) to be completed and remove the group to get rid of the extra wait. Signed-hostap: Jouni Malinen --- wpa_supplicant/p2p_supplicant.c | 47 +++++++++++++++++++++++++++++-- wpa_supplicant/p2p_supplicant.h | 1 + wpa_supplicant/wpa_supplicant_i.h | 1 + wpa_supplicant/wps_supplicant.c | 7 ++++- 4 files changed, 53 insertions(+), 3 deletions(-) diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 719e54983..caf8a5ec0 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -1497,6 +1497,17 @@ void wpas_p2p_group_formation_failed(struct wpa_supplicant *wpa_s) } +static void wpas_p2p_grpform_fail_after_wps(struct wpa_supplicant *wpa_s) +{ + wpa_printf(MSG_DEBUG, "P2P: Reject group formation due to WPS provisioning failure"); + eloop_cancel_timeout(wpas_p2p_group_formation_timeout, + wpa_s->parent, NULL); + eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout, + wpa_s->parent, NULL); + wpa_s->global->p2p_fail_on_wps_complete = 0; +} + + void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s) { if (wpa_s->global->p2p_group_formation != wpa_s) @@ -4496,6 +4507,8 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, os_free(wpa_s->global->add_psk); wpa_s->global->add_psk = NULL; + wpa_s->global->p2p_fail_on_wps_complete = 0; + if (go_intent < 0) go_intent = wpa_s->conf->p2p_go_intent; @@ -5123,9 +5136,14 @@ static void wpas_p2p_idle_update(void *ctx, int idle) if (!wpa_s->ap_iface) return; wpa_printf(MSG_DEBUG, "P2P: GO - group %sidle", idle ? "" : "not "); - if (idle) + if (idle) { + if (wpa_s->global->p2p_fail_on_wps_complete && + wpa_s->p2p_in_provisioning) { + wpas_p2p_grpform_fail_after_wps(wpa_s); + return; + } wpas_p2p_set_group_idle_timeout(wpa_s); - else + } else eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL); } @@ -5244,6 +5262,31 @@ void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s, } wpas_notify_p2p_wps_failed(wpa_s, fail); + + if (wpa_s == wpa_s->global->p2p_group_formation) { + /* + * Allow some time for the failed WPS negotiation exchange to + * complete, but remove the group since group formation cannot + * succeed after provisioning failure. + */ + wpa_printf(MSG_DEBUG, "P2P: WPS step failed during group formation - reject connection from timeout"); + wpa_s->global->p2p_fail_on_wps_complete = 1; + eloop_deplete_timeout(0, 50000, + wpas_p2p_group_formation_timeout, + wpa_s->parent, NULL); + } +} + + +int wpas_p2p_wps_eapol_cb(struct wpa_supplicant *wpa_s) +{ + if (!wpa_s->global->p2p_fail_on_wps_complete || + !wpa_s->p2p_in_provisioning) + return 0; + + wpas_p2p_grpform_fail_after_wps(wpa_s); + + return 1; } diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index 49122caf3..7abfb1256 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -128,6 +128,7 @@ int wpas_p2p_unauthorize(struct wpa_supplicant *wpa_s, const char *addr); int wpas_p2p_disconnect(struct wpa_supplicant *wpa_s); void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s, struct wps_event_fail *fail); +int wpas_p2p_wps_eapol_cb(struct wpa_supplicant *wpa_s); int wpas_p2p_in_progress(struct wpa_supplicant *wpa_s); void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 17e1ca04c..d1ea77bb3 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -258,6 +258,7 @@ struct wpa_global { WPA_CONC_PREF_P2P } conc_pref; unsigned int p2p_per_sta_psk:1; + unsigned int p2p_fail_on_wps_complete:1; #ifdef CONFIG_WIFI_DISPLAY int wifi_display; diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index 6c7508c0a..038c7fae9 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -1,6 +1,6 @@ /* * wpa_supplicant / WPS integration - * Copyright (c) 2008-2013, Jouni Malinen + * Copyright (c) 2008-2014, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -54,6 +54,11 @@ static void wpas_wps_clear_ap_info(struct wpa_supplicant *wpa_s) int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s) { +#ifdef CONFIG_P2P + if (wpas_p2p_wps_eapol_cb(wpa_s) > 0) + return 1; +#endif /* CONFIG_P2P */ + if (!wpa_s->wps_success && wpa_s->current_ssid && eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {