Patchwork P2P: deal with a peer associating while connected

login
register
mail settings
Submitter Johannes Berg
Date Nov. 16, 2011, 9:15 a.m.
Message ID <1321434955.4773.12.camel@jlt3.sipsolutions.net>
Download mbox | patch
Permalink /patch/125963/
State Accepted
Commit 38dcca9ab0c8fec3f29ae13b9a9c49225dab684b
Headers show

Comments

Johannes Berg - Nov. 16, 2011, 9:15 a.m.
From: Johannes Berg <johannes.berg@intel.com>

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 |   54 +++++++++++++++++++++++++++++++-------------------
 1 files changed, 33 insertions(+), 21 deletions(-)
Jouni Malinen - Nov. 16, 2011, 2:37 p.m.
On Wed, Nov 16, 2011 at 10:15:55AM +0100, Johannes Berg wrote:
> 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.

Thanks! Applied.

Patch

diff --git a/src/p2p/p2p_group.c b/src/p2p/p2p_group.c
index 58b24c5..c34a92f 100644
--- a/src/p2p/p2p_group.c
+++ b/src/p2p/p2p_group.c
@@ -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,