P2P: Deal with a peer associating while connected

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>
This commit is contained in:
Johannes Berg 2011-11-16 16:36:40 +02:00 committed by Jouni Malinen
parent 0399f2e4e5
commit 38dcca9ab0

View 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, int p2p_group_notif_assoc(struct p2p_group *group, const u8 *addr,
const u8 *ie, size_t len) 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); m->dev_addr);
} }
p2p_group_remove_member(group, addr);
m->next = group->members; m->next = group->members;
group->members = m; group->members = m;
group->num_members++; 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) void p2p_group_notif_disassoc(struct p2p_group *group, const u8 *addr)
{ {
struct p2p_group_member *m, *prev; if (p2p_group_remove_member(group, addr)) {
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--;
wpa_msg(group->p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Remove " wpa_msg(group->p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Remove "
"client " MACSTR " from group; num_members=%u/%u", "client " MACSTR " from group; num_members=%u/%u",
MAC2STR(addr), group->num_members, MAC2STR(addr), group->num_members,