P2P: Deal with a peer associating while connected
authorJohannes Berg <johannes.berg@intel.com>
Wed, 16 Nov 2011 14:36:40 +0000 (16:36 +0200)
committerJouni Malinen <j@w1.fi>
Wed, 16 Nov 2011 14:36:40 +0000 (16:36 +0200)
If a P2P client associates with the group while it is
already associated, two member entries may be added to
the group which also confuses num_members counting.

Deal with this by removing the existing entry first
before adding a new one.

I think the way Reinette ran into this was due to our
tx_sync implementation in iwlagn, mac80211 might have
queued two association frames thinking the first one
just failed, but both only went out after the sync was
really successful (which tx_sync doesn't wait for).

Reported-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-hostap: Johannes Berg <johannes.berg@intel.com>

src/p2p/p2p_group.c

index 58b24c5..c34a92f 100644 (file)
@@ -313,6 +313,36 @@ static struct wpabuf * p2p_build_client_info(const u8 *addr,
 }
 
 
+static int p2p_group_remove_member(struct p2p_group *group, const u8 *addr)
+{
+       struct p2p_group_member *m, *prev;
+
+       if (group == NULL)
+               return 0;
+
+       m = group->members;
+       prev = NULL;
+       while (m) {
+               if (os_memcmp(m->addr, addr, ETH_ALEN) == 0)
+                       break;
+               prev = m;
+               m = m->next;
+       }
+
+       if (m == NULL)
+               return 0;
+
+       if (prev)
+               prev->next = m->next;
+       else
+               group->members = m->next;
+       p2p_group_free_member(m);
+       group->num_members--;
+
+       return 1;
+}
+
+
 int p2p_group_notif_assoc(struct p2p_group *group, const u8 *addr,
                          const u8 *ie, size_t len)
 {
@@ -332,6 +362,8 @@ int p2p_group_notif_assoc(struct p2p_group *group, const u8 *addr,
                                                       m->dev_addr);
        }
 
+       p2p_group_remove_member(group, addr);
+
        m->next = group->members;
        group->members = m;
        group->num_members++;
@@ -374,27 +406,7 @@ struct wpabuf * p2p_group_assoc_resp_ie(struct p2p_group *group, u8 status)
 
 void p2p_group_notif_disassoc(struct p2p_group *group, const u8 *addr)
 {
-       struct p2p_group_member *m, *prev;
-
-       if (group == NULL)
-               return;
-
-       m = group->members;
-       prev = NULL;
-       while (m) {
-               if (os_memcmp(m->addr, addr, ETH_ALEN) == 0)
-                       break;
-               prev = m;
-               m = m->next;
-       }
-
-       if (m) {
-               if (prev)
-                       prev->next = m->next;
-               else
-                       group->members = m->next;
-               p2p_group_free_member(m);
-               group->num_members--;
+       if (p2p_group_remove_member(group, addr)) {
                wpa_msg(group->p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Remove "
                        "client " MACSTR " from group; num_members=%u/%u",
                        MAC2STR(addr), group->num_members,