From 1a9c618d3f465b974a724dc2cb3e4030837e2982 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 27 Feb 2012 17:23:41 +0200 Subject: [PATCH] P2P: Fix remain-on-channel use with PD/Invitation Request while in Listen If Listen state was in progress on another channel when a request to send an Action frame (e.g., Provision Discovery Request or Invitation Request to a peer on the peer's Listen channel that is different from our Listenc hannel) is issued, wpa_supplicant tried to use concurrent remain-on-channel operations. While some drivers can handle this cleanly, there are drivers that don't and wpa_supplicant is not expected to request concurrent remain-on-channel operations. Fix this by cancelling the ongoing remain-on-channel with stop_listen prior to sending the Action frame on another channel. If a P2P search was in progress, it will be continued after the timeout on the new operation. Signed-hostap: Jouni Malinen --- src/p2p/p2p.c | 10 ++++++++++ src/p2p/p2p_i.h | 1 + src/p2p/p2p_invitation.c | 2 ++ src/p2p/p2p_pd.c | 2 ++ 4 files changed, 15 insertions(+) diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 2b003aee8..b196e6fdd 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -1024,11 +1024,21 @@ void p2p_stop_find_for_freq(struct p2p_data *p2p, int freq) p2p->go_neg_peer = NULL; p2p->sd_peer = NULL; p2p->invite_peer = NULL; + p2p_stop_listen_for_freq(p2p, freq); +} + + +void p2p_stop_listen_for_freq(struct p2p_data *p2p, int freq) +{ if (freq > 0 && p2p->drv_in_listen == freq && p2p->in_listen) { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip stop_listen " "since we are on correct channel for response"); return; } + if (p2p->in_listen) { + p2p->in_listen = 0; + p2p_clear_timeout(p2p); + } if (p2p->drv_in_listen) { /* * The driver may not deliver callback to p2p_listen_end() diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index 8f9449eab..eecef5488 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -667,5 +667,6 @@ void p2p_build_ssid(struct p2p_data *p2p, u8 *ssid, size_t *ssid_len); int p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst, const u8 *src, const u8 *bssid, const u8 *buf, size_t len, unsigned int wait_time); +void p2p_stop_listen_for_freq(struct p2p_data *p2p, int freq); #endif /* P2P_I_H */ diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c index 417f1e7ea..1e6ed7d71 100644 --- a/src/p2p/p2p_invitation.c +++ b/src/p2p/p2p_invitation.c @@ -344,6 +344,8 @@ int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev, req = p2p_build_invitation_req(p2p, dev, go_dev_addr); if (req == NULL) return -1; + if (p2p->state != P2P_IDLE) + p2p_stop_listen_for_freq(p2p, freq); wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Sending Invitation Request"); p2p_set_state(p2p, P2P_INVITE); diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c index 55a3b908e..ca248aed6 100644 --- a/src/p2p/p2p_pd.c +++ b/src/p2p/p2p_pd.c @@ -316,6 +316,8 @@ int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev, if (req == NULL) return -1; + if (p2p->state != P2P_IDLE) + p2p_stop_listen_for_freq(p2p, freq); p2p->pending_action_state = P2P_PENDING_PD; if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr, p2p->cfg->dev_addr, dev->info.p2p_device_addr,