P2PS: Send follow-on PD response only if status is 12
authorMax Stepanov <Max.Stepanov@intel.com>
Thu, 24 Sep 2015 17:37:54 +0000 (20:37 +0300)
committerJouni Malinen <j@w1.fi>
Wed, 7 Oct 2015 14:07:21 +0000 (17:07 +0300)
When a follow-on PD request is received, peer should not send a
follow-on PD response except the case when the PD request status value
is 12 (Success: accepted by user). Previously, the wpa_supplicant
implementation behaved differently sending the follow-on PD Response on
any follow-on PD Request.

Fix the issue by adding the following changes:

1. Don't send PD Response if the follow-on PD Request status is
   different than 12 (seeker side).
2. Don't wait for the follow-on PD Response if the follow-on PD
   Request was sent with the status different than 12 (advertiser
   side).
3. If the follow-on PD Request was sent with the status different
   than 12 use the follow-on PD Request ACK as PD completion event
   (advertiser side).
4. Notify ASP about the PD completion by sending P2PS-PROV-DONE with
   the PD Request status (advertiser side).

Signed-off-by: Max Stepanov <Max.Stepanov@intel.com>
src/p2p/p2p.c
src/p2p/p2p_pd.c

index c876f19..6984cb4 100644 (file)
@@ -3327,6 +3327,43 @@ static void p2p_prov_disc_cb(struct p2p_data *p2p, int success)
        }
 
        /*
+        * 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.
         */
index 8900945..58fb470 100644 (file)
@@ -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");
+
+       /*
+        * 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);
-               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 */