From d95c5994c8038cb09a70cc6400584c82097e7c31 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 15 Jun 2015 23:34:11 +0300 Subject: [PATCH] P2P: Fix group interface addition failure properly for concurrent case It was possible for a P2P group formation failure to result in a concurrent station mode operation getting disconnected in the specific error case where group interface addition fails after a successful GO Negotiation. Fix this by skipping the wpas_p2p_group_delete() call in this specific case since the group interface does not exists anymore at the point wpas_group_formation_completed() gets called. Signed-off-by: Jouni Malinen --- wpa_supplicant/p2p_supplicant.c | 25 +++++++++++++++---------- wpa_supplicant/p2p_supplicant.h | 1 - 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index df7565f17..730d79352 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -126,6 +126,8 @@ static void wpas_p2p_psk_failure_removal(void *eloop_ctx, void *timeout_ctx); static void wpas_p2p_group_deinit(struct wpa_supplicant *wpa_s); static int wpas_p2p_add_group_interface(struct wpa_supplicant *wpa_s, enum wpa_driver_if_type type); +static void wpas_p2p_group_formation_failed(struct wpa_supplicant *wpa_s, + int already_deleted); /* @@ -1231,7 +1233,7 @@ static void wpas_p2p_group_started(struct wpa_supplicant *wpa_s, static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s, - int success) + int success, int already_deleted) { struct wpa_ssid *ssid; int client; @@ -1256,6 +1258,8 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s, if (!success) { wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_FORMATION_FAILURE); + if (already_deleted) + return; wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_FORMATION_FAILED); return; @@ -2020,17 +2024,18 @@ static void wpas_p2p_group_formation_timeout(void *eloop_ctx, { struct wpa_supplicant *wpa_s = eloop_ctx; wpa_printf(MSG_DEBUG, "P2P: Group Formation timed out"); - wpas_p2p_group_formation_failed(wpa_s); + wpas_p2p_group_formation_failed(wpa_s, 0); } -void wpas_p2p_group_formation_failed(struct wpa_supplicant *wpa_s) +static void wpas_p2p_group_formation_failed(struct wpa_supplicant *wpa_s, + int already_deleted) { eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->parent, NULL); if (wpa_s->global->p2p) p2p_group_formation_failed(wpa_s->global->p2p); - wpas_group_formation_completed(wpa_s, 0); + wpas_group_formation_completed(wpa_s, 0, already_deleted); } @@ -2111,7 +2116,7 @@ static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res) wpas_p2p_remove_pending_group_interface(wpa_s); eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL); - wpas_p2p_group_formation_failed(wpa_s); + wpas_p2p_group_formation_failed(wpa_s, 1); return; } if (group_wpa_s != wpa_s) { @@ -5748,7 +5753,7 @@ void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr, } if (wpa_s->global->p2p) p2p_wps_success_cb(wpa_s->global->p2p, peer_addr); - wpas_group_formation_completed(wpa_s, 1); + wpas_group_formation_completed(wpa_s, 1, 0); } @@ -6765,7 +6770,7 @@ int wpas_p2p_notif_pbc_overlap(struct wpa_supplicant *wpa_s) "session overlap"); if (wpa_s != wpa_s->parent) wpa_msg_ctrl(wpa_s->parent, MSG_INFO, WPS_EVENT_OVERLAP); - wpas_p2p_group_formation_failed(wpa_s); + wpas_p2p_group_formation_failed(wpa_s, 0); return 1; } @@ -6875,7 +6880,7 @@ int wpas_p2p_cancel(struct wpa_supplicant *wpa_s) eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->parent, NULL); if (wpa_s->p2p_in_provisioning) { - wpas_group_formation_completed(wpa_s, 0); + wpas_group_formation_completed(wpa_s, 0, 0); break; } wpas_p2p_group_delete(wpa_s, @@ -6885,7 +6890,7 @@ int wpas_p2p_cancel(struct wpa_supplicant *wpa_s) wpa_printf(MSG_DEBUG, "P2P: Interface %s in invitation found - cancelling", wpa_s->ifname); found = 1; - wpas_p2p_group_formation_failed(wpa_s); + wpas_p2p_group_formation_failed(wpa_s, 0); } } @@ -7081,7 +7086,7 @@ void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s, */ if (wpa_s->global->p2p) p2p_wps_success_cb(wpa_s->global->p2p, addr); - wpas_group_formation_completed(wpa_s, 1); + wpas_group_formation_completed(wpa_s, 1, 0); } } if (!wpa_s->p2p_go_group_formation_completed) { diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index ed2e54299..1df34d084 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -66,7 +66,6 @@ int wpas_p2p_listen_start(struct wpa_supplicant *wpa_s, unsigned int timeout); int wpas_p2p_assoc_req_ie(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, u8 *buf, size_t len, int p2p_group); void wpas_p2p_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ies); -void wpas_p2p_group_formation_failed(struct wpa_supplicant *wpa_s); u64 wpas_p2p_sd_request(struct wpa_supplicant *wpa_s, const u8 *dst, const struct wpabuf *tlvs); u64 wpas_p2p_sd_request_asp(struct wpa_supplicant *wpa_s, const u8 *dst, u8 id,