diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index c876f19ce..6984cb428 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -3326,6 +3326,43 @@ static void p2p_prov_disc_cb(struct p2p_data *p2p, int success) return; } + /* + * If after PD Request the peer doesn't expect to receive PD Response + * the PD Request ACK indicates a completion of the current PD. This + * happens only on the advertiser side sending the follow-on PD Request + * with the status different than 12 (Success: accepted by user). + */ + if (p2p->p2ps_prov && !p2p->p2ps_prov->pd_seeker && + p2p->p2ps_prov->status != P2P_SC_SUCCESS_DEFERRED) { + p2p_dbg(p2p, "P2PS PD completion on Follow-on PD Request ACK"); + + if (p2p->send_action_in_progress) { + p2p->send_action_in_progress = 0; + p2p->cfg->send_action_done(p2p->cfg->cb_ctx); + } + + p2p->pending_action_state = P2P_NO_PENDING_ACTION; + + if (p2p->cfg->p2ps_prov_complete) { + p2p->cfg->p2ps_prov_complete( + p2p->cfg->cb_ctx, + p2p->p2ps_prov->status, + p2p->p2ps_prov->adv_mac, + p2p->p2ps_prov->adv_mac, + p2p->p2ps_prov->session_mac, + NULL, p2p->p2ps_prov->adv_id, + p2p->p2ps_prov->session_id, + 0, 0, NULL, 0, 0, 0, + NULL, NULL, 0); + } + + if (p2p->user_initiated_pd) + p2p_reset_pending_pd(p2p); + + p2ps_prov_free(p2p); + return; + } + /* * This postponing, of resetting pending_action_state, needs to be * done only for user initiated PD requests and not internal ones. diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c index 890094551..58fb470ed 100644 --- a/src/p2p/p2p_pd.c +++ b/src/p2p/p2p_pd.c @@ -728,38 +728,46 @@ out: config_methods = msg.wps_config_methods; else config_methods = 0; - resp = p2p_build_prov_disc_resp(p2p, dev, msg.dialog_token, reject, - config_methods, adv_id, - msg.group_id, msg.group_id_len, - msg.persistent_ssid, - msg.persistent_ssid_len, - (const u8 *) &resp_fcap, - sizeof(resp_fcap)); - if (resp == NULL) { - p2p_parse_free(&msg); - return; - } - p2p_dbg(p2p, "Sending Provision Discovery Response"); - if (rx_freq > 0) - freq = rx_freq; - else - freq = p2p_channel_to_freq(p2p->cfg->reg_class, - p2p->cfg->channel); - if (freq < 0) { - p2p_dbg(p2p, "Unknown regulatory class/channel"); - wpabuf_free(resp); - p2p_parse_free(&msg); - return; - } - p2p->pending_action_state = P2P_PENDING_PD_RESPONSE; - if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, - p2p->cfg->dev_addr, - wpabuf_head(resp), wpabuf_len(resp), 200) < 0) { - p2p_dbg(p2p, "Failed to send Action frame"); - } else - p2p->send_action_in_progress = 1; - wpabuf_free(resp); + /* + * Send PD Response for an initial PD Request or for follow-on + * PD Request with P2P_SC_SUCCESS_DEFERRED status. + */ + if (!msg.status || *msg.status == P2P_SC_SUCCESS_DEFERRED) { + resp = p2p_build_prov_disc_resp(p2p, dev, msg.dialog_token, + reject, config_methods, adv_id, + msg.group_id, msg.group_id_len, + msg.persistent_ssid, + msg.persistent_ssid_len, + (const u8 *) &resp_fcap, + sizeof(resp_fcap)); + if (!resp) { + p2p_parse_free(&msg); + return; + } + p2p_dbg(p2p, "Sending Provision Discovery Response"); + if (rx_freq > 0) + freq = rx_freq; + else + freq = p2p_channel_to_freq(p2p->cfg->reg_class, + p2p->cfg->channel); + if (freq < 0) { + p2p_dbg(p2p, "Unknown regulatory class/channel"); + wpabuf_free(resp); + p2p_parse_free(&msg); + return; + } + p2p->pending_action_state = P2P_PENDING_PD_RESPONSE; + if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, + p2p->cfg->dev_addr, + wpabuf_head(resp), wpabuf_len(resp), + 200) < 0) + p2p_dbg(p2p, "Failed to send Action frame"); + else + p2p->send_action_in_progress = 1; + + wpabuf_free(resp); + } if (!p2p->cfg->p2ps_prov_complete) { /* Don't emit anything */