]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P: Reject group formation on WPS provisioning failure
authorJouni Malinen <j@w1.fi>
Mon, 6 Jan 2014 15:56:50 +0000 (17:56 +0200)
committerJouni Malinen <j@w1.fi>
Tue, 7 Jan 2014 08:45:12 +0000 (10:45 +0200)
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 <j@w1.fi>

wpa_supplicant/p2p_supplicant.c
wpa_supplicant/p2p_supplicant.h
wpa_supplicant/wpa_supplicant_i.h
wpa_supplicant/wps_supplicant.c

index 719e5498363a3ff6a4265102f29031034e084ac2..caf8a5ec02a2f3122d78b9e391487118691b0eae 100644 (file)
@@ -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;
 }
 
 
index 49122caf37715a8527bfb1ecd983b5632e8255fa..7abfb1256e6f7367d9267344a365a7dc1a61fad0 100644 (file)
@@ -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);
index 17e1ca04c5864bd740011331f5410c91aa27ba68..d1ea77bb387198ad609b559b5caa478524cd435e 100644 (file)
@@ -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;
index 6c7508c0aeb61f99099341e3a0631720eb42a796..038c7fae9d5debb98d4f06b5a5a54c4fc3d51fda 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * wpa_supplicant / WPS integration
- * Copyright (c) 2008-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2008-2014, Jouni Malinen <j@w1.fi>
  *
  * 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)) {