]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P: Remove persistent group peer if it rejects invitation
authorJouni Malinen <jouni@qca.qualcomm.com>
Fri, 15 Mar 2013 14:31:31 +0000 (16:31 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 15 Mar 2013 14:43:06 +0000 (16:43 +0200)
If a peer replies to persistent group invitation with status code 8
(unknown group), remove the peer from the p2p_client_list if we are the
GO or remove the persistent group if we are the P2P client since it
looks like that the peer has dropped persistent group credentials and
the provisioning step needs to be executed again.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

src/p2p/p2p.c
src/p2p/p2p.h
src/p2p/p2p_invitation.c
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index d38e9c59d00b8b0d7aaee570784e475b3146f8f2..4418bb32b280c56975210536fd0836dc51644bbb 100644 (file)
@@ -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);
        }
index eb57a3a5170480aad53a4d4dbb2c1458b298af02..d2fa68c5a3995f1f73327a4cecec8226a4037f26 100644 (file)
@@ -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
index 8b160b04761304cfb85f4c0845268dca6a4d6c6e..6452ca20825201f685ece59d1f731c31e23d8622 100644 (file)
@@ -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);
 
index afc0dfb5c28e3cb47980d199c52daed205691682..bbcde8f377dfa38e4f3097a3c535ac7684587ba0 100644 (file)
@@ -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);
index 42a475f12f9e4ded739ef5a230d67564d6070919..908d7986bb936ceb7fc5488171c2a67528b7821c 100644 (file)
@@ -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);
 
index 4ec15c12836c26b77e36258ed486316b17e29203..5465c4fa45c1334e1a886f18dce04b2905b0e18b 100644 (file)
@@ -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 */