diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index d38e9c59d..4418bb32b 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -3373,7 +3373,8 @@ static void p2p_timeout_invite_listen(struct p2p_data *p2p) "P2P: Invitation Request retry limit reached"); if (p2p->cfg->invitation_result) p2p->cfg->invitation_result( - p2p->cfg->cb_ctx, -1, NULL, NULL); + p2p->cfg->cb_ctx, -1, NULL, NULL, + p2p->invite_peer->info.p2p_device_addr); } p2p_set_state(p2p, P2P_IDLE); } diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index eb57a3a51..d2fa68c5a 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -730,6 +730,7 @@ struct p2p_config { * @status: Negotiation result (Status Code) * @bssid: P2P Group BSSID or %NULL if not received * @channels: Available operating channels for the group + * @addr: Peer address * * This callback is used to indicate result of an Invitation procedure * started with a call to p2p_invite(). The indicated status code is @@ -738,7 +739,8 @@ struct p2p_config { * local failure in transmitting the Invitation Request. */ void (*invitation_result)(void *ctx, int status, const u8 *bssid, - const struct p2p_channels *channels); + const struct p2p_channels *channels, + const u8 *addr); /** * go_connected - Check whether we are connected to a GO diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c index 8b160b047..6452ca208 100644 --- a/src/p2p/p2p_invitation.c +++ b/src/p2p/p2p_invitation.c @@ -466,7 +466,7 @@ void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa, if (p2p->cfg->invitation_result) p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status, - msg.group_bssid, channels); + msg.group_bssid, channels, sa); p2p_parse_free(&msg); diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index afc0dfb5c..bbcde8f37 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -2510,8 +2510,68 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid, } +static void wpas_remove_persistent_peer(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, + const u8 *peer) +{ + size_t i; + + if (ssid == NULL) + return; + + for (i = 0; ssid->p2p_client_list && i < ssid->num_p2p_clients; i++) { + if (os_memcmp(ssid->p2p_client_list + i * ETH_ALEN, peer, + ETH_ALEN) == 0) + break; + } + if (i >= ssid->num_p2p_clients) { + if (ssid->mode != WPAS_MODE_P2P_GO && + os_memcmp(ssid->bssid, peer, ETH_ALEN) == 0) { + wpa_printf(MSG_DEBUG, "P2P: Remove persistent group %d " + "due to invitation result", ssid->id); + wpas_notify_network_removed(wpa_s, ssid); + wpa_config_remove_network(wpa_s->conf, ssid->id); + return; + } + return; /* Peer not found in client list */ + } + + wpa_printf(MSG_DEBUG, "P2P: Remove peer " MACSTR " from persistent " + "group %d client list due to invitation result", + MAC2STR(peer), ssid->id); + os_memmove(ssid->p2p_client_list + i * ETH_ALEN, + ssid->p2p_client_list + (i + 1) * ETH_ALEN, + (ssid->num_p2p_clients - i - 1) * ETH_ALEN); + ssid->num_p2p_clients--; +#ifndef CONFIG_NO_CONFIG_WRITE + if (wpa_s->parent->conf->update_config && + wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf)) + wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration"); +#endif /* CONFIG_NO_CONFIG_WRITE */ +} + + +static void wpas_remove_persistent_client(struct wpa_supplicant *wpa_s, + const u8 *peer) +{ + struct wpa_ssid *ssid; + + wpa_s = wpa_s->global->p2p_invite_group; + if (wpa_s == NULL) + return; /* No known invitation group */ + ssid = wpa_s->current_ssid; + if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO || + !ssid->p2p_persistent_group) + return; /* Not operating as a GO in persistent group */ + ssid = wpas_p2p_get_persistent(wpa_s->parent, peer, + ssid->ssid, ssid->ssid_len); + wpas_remove_persistent_peer(wpa_s, ssid, peer); +} + + static void wpas_invitation_result(void *ctx, int status, const u8 *bssid, - const struct p2p_channels *channels) + const struct p2p_channels *channels, + const u8 *peer) { struct wpa_supplicant *wpa_s = ctx; struct wpa_ssid *ssid; @@ -2526,8 +2586,13 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid, } wpas_notify_p2p_invitation_result(wpa_s, status, bssid); - if (wpa_s->pending_invite_ssid_id == -1) + wpa_printf(MSG_DEBUG, "P2P: Invitation result - status=%d peer=" MACSTR, + status, MAC2STR(peer)); + if (wpa_s->pending_invite_ssid_id == -1) { + if (status == P2P_SC_FAIL_UNKNOWN_GROUP) + wpas_remove_persistent_client(wpa_s, peer); return; /* Invitation to active group */ + } if (status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) { wpa_printf(MSG_DEBUG, "P2P: Waiting for peer to start another " @@ -2536,6 +2601,11 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid, } if (status != P2P_SC_SUCCESS) { + if (status == P2P_SC_FAIL_UNKNOWN_GROUP) { + ssid = wpa_config_get_network( + wpa_s->conf, wpa_s->pending_invite_ssid_id); + wpas_remove_persistent_peer(wpa_s, ssid, peer); + } wpas_p2p_remove_pending_group_interface(wpa_s); return; } @@ -4687,6 +4757,7 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr, int force_freq = 0, oper_freq = 0; int res; + wpa_s->global->p2p_invite_group = NULL; if (peer_addr) os_memcpy(wpa_s->p2p_auth_invite, peer_addr, ETH_ALEN); else @@ -4779,6 +4850,7 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname, return -1; } + wpa_s->global->p2p_invite_group = wpa_s; persistent = ssid->p2p_persistent_group && wpas_p2p_get_persistent(wpa_s->parent, peer_addr, ssid->ssid, ssid->ssid_len); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 42a475f12..908d7986b 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -3125,6 +3125,8 @@ int wpa_supplicant_remove_iface(struct wpa_global *global, if (global->p2p_group_formation == wpa_s) global->p2p_group_formation = NULL; + if (global->p2p_invite_group == wpa_s) + global->p2p_invite_group = NULL; wpa_supplicant_deinit_iface(wpa_s, 1, terminate); os_free(wpa_s); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 4ec15c128..5465c4fa4 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -228,6 +228,7 @@ struct wpa_global { struct p2p_data *p2p; struct wpa_supplicant *p2p_init_wpa_s; struct wpa_supplicant *p2p_group_formation; + struct wpa_supplicant *p2p_invite_group; u8 p2p_dev_addr[ETH_ALEN]; struct dl_list p2p_srv_bonjour; /* struct p2p_srv_bonjour */ struct dl_list p2p_srv_upnp; /* struct p2p_srv_upnp */