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 <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2015-06-15 23:34:11 +03:00 committed by Jouni Malinen
parent e12c4004e4
commit d95c5994c8
2 changed files with 15 additions and 11 deletions

View file

@ -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 void wpas_p2p_group_deinit(struct wpa_supplicant *wpa_s);
static int wpas_p2p_add_group_interface(struct wpa_supplicant *wpa_s, static int wpas_p2p_add_group_interface(struct wpa_supplicant *wpa_s,
enum wpa_driver_if_type type); 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, static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
int success) int success, int already_deleted)
{ {
struct wpa_ssid *ssid; struct wpa_ssid *ssid;
int client; int client;
@ -1256,6 +1258,8 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
if (!success) { if (!success) {
wpa_msg_global(wpa_s->parent, MSG_INFO, wpa_msg_global(wpa_s->parent, MSG_INFO,
P2P_EVENT_GROUP_FORMATION_FAILURE); P2P_EVENT_GROUP_FORMATION_FAILURE);
if (already_deleted)
return;
wpas_p2p_group_delete(wpa_s, wpas_p2p_group_delete(wpa_s,
P2P_GROUP_REMOVAL_FORMATION_FAILED); P2P_GROUP_REMOVAL_FORMATION_FAILED);
return; return;
@ -2020,17 +2024,18 @@ static void wpas_p2p_group_formation_timeout(void *eloop_ctx,
{ {
struct wpa_supplicant *wpa_s = eloop_ctx; struct wpa_supplicant *wpa_s = eloop_ctx;
wpa_printf(MSG_DEBUG, "P2P: Group Formation timed out"); 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, eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
wpa_s->parent, NULL); wpa_s->parent, NULL);
if (wpa_s->global->p2p) if (wpa_s->global->p2p)
p2p_group_formation_failed(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); wpas_p2p_remove_pending_group_interface(wpa_s);
eloop_cancel_timeout(wpas_p2p_long_listen_timeout, eloop_cancel_timeout(wpas_p2p_long_listen_timeout,
wpa_s, NULL); wpa_s, NULL);
wpas_p2p_group_formation_failed(wpa_s); wpas_p2p_group_formation_failed(wpa_s, 1);
return; return;
} }
if (group_wpa_s != wpa_s) { 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) if (wpa_s->global->p2p)
p2p_wps_success_cb(wpa_s->global->p2p, peer_addr); 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"); "session overlap");
if (wpa_s != wpa_s->parent) if (wpa_s != wpa_s->parent)
wpa_msg_ctrl(wpa_s->parent, MSG_INFO, WPS_EVENT_OVERLAP); 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; return 1;
} }
@ -6875,7 +6880,7 @@ int wpas_p2p_cancel(struct wpa_supplicant *wpa_s)
eloop_cancel_timeout(wpas_p2p_group_formation_timeout, eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
wpa_s->parent, NULL); wpa_s->parent, NULL);
if (wpa_s->p2p_in_provisioning) { if (wpa_s->p2p_in_provisioning) {
wpas_group_formation_completed(wpa_s, 0); wpas_group_formation_completed(wpa_s, 0, 0);
break; break;
} }
wpas_p2p_group_delete(wpa_s, 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_printf(MSG_DEBUG, "P2P: Interface %s in invitation found - cancelling",
wpa_s->ifname); wpa_s->ifname);
found = 1; 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) if (wpa_s->global->p2p)
p2p_wps_success_cb(wpa_s->global->p2p, addr); 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) { if (!wpa_s->p2p_go_group_formation_completed) {

View file

@ -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, int wpas_p2p_assoc_req_ie(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
u8 *buf, size_t len, int p2p_group); u8 *buf, size_t len, int p2p_group);
void wpas_p2p_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ies); 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, u64 wpas_p2p_sd_request(struct wpa_supplicant *wpa_s, const u8 *dst,
const struct wpabuf *tlvs); const struct wpabuf *tlvs);
u64 wpas_p2p_sd_request_asp(struct wpa_supplicant *wpa_s, const u8 *dst, u8 id, u64 wpas_p2p_sd_request_asp(struct wpa_supplicant *wpa_s, const u8 *dst, u8 id,