P2P: Assign GO tie breaker bit at the same time with dialog token

Commit 624b4d5a64 changed GO Negotiation
to use the same Dialog Token value for all retransmissions of the GO
Negotiation Request within the same session. However, it did leave the
tie breaker bit changing for each frame. While this should not have
caused issues for most cases, it looks like there are possible sequences
where the peer may end up replying to two GO Negotiation Request frames
with different tie breaker values. If in such a case the different GO
Negotiation Response frames are used at each device, GO role
determination may result in conflicting results when same GO intent is
used.

Fix this by assigning the tie breaker value at the same time with the
dialog token (i.e., when processing the p2p_connect command instead of
for each transmitted GO Negotiation Request frame) to avoid issues with
GO selection.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2013-02-26 16:56:48 +02:00 committed by Jouni Malinen
parent f8361e3d68
commit 003c45804f
3 changed files with 6 additions and 5 deletions

View file

@ -1368,12 +1368,14 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
else { else {
dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG; dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG;
/* /*
* Assign dialog token here to use the same value in each * Assign dialog token and tie breaker here to use the same
* retry within the same GO Negotiation exchange. * values in each retry within the same GO Negotiation exchange.
*/ */
dev->dialog_token++; dev->dialog_token++;
if (dev->dialog_token == 0) if (dev->dialog_token == 0)
dev->dialog_token = 1; dev->dialog_token = 1;
dev->tie_breaker = p2p->next_tie_breaker;
p2p->next_tie_breaker = !p2p->next_tie_breaker;
} }
dev->connect_reqs = 0; dev->connect_reqs = 0;
dev->go_neg_req_sent = 0; dev->go_neg_req_sent = 0;

View file

@ -161,9 +161,7 @@ static struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p,
p2p_buf_add_capability(buf, p2p->dev_capab & p2p_buf_add_capability(buf, p2p->dev_capab &
~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY,
group_capab); group_capab);
p2p_buf_add_go_intent(buf, (p2p->go_intent << 1) | p2p_buf_add_go_intent(buf, (p2p->go_intent << 1) | peer->tie_breaker);
p2p->next_tie_breaker);
p2p->next_tie_breaker = !p2p->next_tie_breaker;
p2p_buf_add_config_timeout(buf, p2p->go_timeout, p2p->client_timeout); p2p_buf_add_config_timeout(buf, p2p->go_timeout, p2p->client_timeout);
p2p_buf_add_listen_channel(buf, p2p->cfg->country, p2p->cfg->reg_class, p2p_buf_add_listen_channel(buf, p2p->cfg->country, p2p->cfg->reg_class,
p2p->cfg->channel); p2p->cfg->channel);

View file

@ -52,6 +52,7 @@ struct p2p_device {
int go_neg_req_sent; int go_neg_req_sent;
enum p2p_go_state go_state; enum p2p_go_state go_state;
u8 dialog_token; u8 dialog_token;
u8 tie_breaker;
u8 intended_addr[ETH_ALEN]; u8 intended_addr[ETH_ALEN];
char country[3]; char country[3];