P2PS: Process channels in PD Response
authorIlan Peer <ilan.peer@intel.com>
Thu, 8 Oct 2015 09:36:00 +0000 (12:36 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 11 Oct 2015 18:42:03 +0000 (21:42 +0300)
In case the P2PS PD Response includes the P2P Channel List attribute,
update the peer device supported channels and verify that the local
device has common channels with the peer (only a sanity check).

If the Operating Channel attribute is included in the response, check
that it is included in the intersection and store it as the peer's
operating frequency (so it could later be used in the join flow, etc.).

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
src/p2p/p2p_pd.c

index 23fbf2e..25e2f3c 100644 (file)
@@ -1365,10 +1365,55 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
                passwd_id = DEV_PW_P2PS_DEFAULT;
        }
 
-       if ((msg.conn_cap || msg.persistent_dev) &&
-           (status == P2P_SC_SUCCESS || status == P2P_SC_SUCCESS_DEFERRED) &&
+       if ((status == P2P_SC_SUCCESS || status == P2P_SC_SUCCESS_DEFERRED) &&
            p2p->p2ps_prov) {
+               dev->oper_freq = 0;
+
+               /*
+                * Save the reported channel list and operating frequency.
+                * Note that the specification mandates that the responder
+                * should include in the channel list only channels reported by
+                * the initiator, so this is only a sanity check, and if this
+                * fails the flow would continue, although it would probably
+                * fail. Same is true for the operating channel.
+                */
+               if (msg.channel_list && msg.channel_list_len &&
+                   p2p_peer_channels_check(p2p, &p2p->channels, dev,
+                                           msg.channel_list,
+                                           msg.channel_list_len) < 0)
+                       p2p_dbg(p2p, "P2PS PD Response - no common channels");
+
+               if (msg.operating_channel) {
+                       if (p2p_channels_includes(&p2p->channels,
+                                                 msg.operating_channel[3],
+                                                 msg.operating_channel[4]) &&
+                           p2p_channels_includes(&dev->channels,
+                                                 msg.operating_channel[3],
+                                                 msg.operating_channel[4])) {
+                               dev->oper_freq =
+                                       p2p_channel_to_freq(
+                                               msg.operating_channel[3],
+                                               msg.operating_channel[4]);
+                       } else {
+                               p2p_dbg(p2p,
+                                       "P2PS PD Response - invalid operating channel");
+                       }
+               }
+
                if (p2p->cfg->p2ps_prov_complete) {
+                       if (conncap == P2PS_SETUP_GROUP_OWNER) {
+                               u8 tmp;
+
+                               /*
+                                * Re-select the operating channel as it is
+                                * possible that original channel is no longer
+                                * valid. This should not really fail.
+                                */
+                               if (p2p_go_select_channel(p2p, dev, &tmp) < 0)
+                                       p2p_dbg(p2p,
+                                               "P2PS PD channel selection failed");
+                       }
+
                        p2p->cfg->p2ps_prov_complete(
                                p2p->cfg->cb_ctx, status, sa, adv_mac,
                                p2p->p2ps_prov->session_mac,