diff mbox

[13/23] P2PS: Process channels in PD request

Message ID 1443116293-9323-14-git-send-email-ilan.peer@intel.com
State Changes Requested
Headers show

Commit Message

Peer, Ilan Sept. 24, 2015, 5:38 p.m. UTC
In case that the P2PS PD request includes the P2P channel
list attribute, update the peer device supported channels and
check if we have common channels with the peer that can be used
for the connection establishment based on the connection
capabilities:

1. In case of P2PS PD request with no common channels, defer
   the flow unless auto accept equals true and the connection
   capabilities equals NEW (in which case the channels would be
   negotiated in the GoN).

2. In case of Follow up P2PS PD request with no common channels,
   reject the request unless the connection capability is NEW.

In addition, in case of a successful P2PS PD, save the device
operating frequency (so it can be later used for join flow etc.)

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
---
 src/p2p/p2p_pd.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 72 insertions(+), 4 deletions(-)
diff mbox

Patch

diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c
index d354f76..54db139 100644
--- a/src/p2p/p2p_pd.c
+++ b/src/p2p/p2p_pd.c
@@ -321,10 +321,6 @@  static struct wpabuf * p2p_build_prov_disc_resp(struct p2p_data *p2p,
 
 		/* Add Operating Channel if conncap indicates GO */
 		if (persist || (prov->conncap & P2PS_SETUP_GROUP_OWNER)) {
-			u8 tmp;
-
-			p2p_go_select_channel(p2p, dev, &tmp);
-
 			if (p2p->op_reg_class && p2p->op_channel)
 				p2p_buf_add_operating_channel(
 					buf, p2p->cfg->country,
@@ -740,6 +736,52 @@  void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
 			auto_accept = 0;
 		}
 
+		if ((remote_conncap & (P2PS_SETUP_NEW | P2PS_SETUP_CLIENT) ||
+		     msg.persistent_dev) &&
+		    msg.channel_list && msg.channel_list_len &&
+		    (p2p_peer_channels_check(p2p, &p2p->channels, dev,
+					     msg.channel_list,
+					     msg.channel_list_len) < 0) &&
+		    conncap != P2PS_SETUP_NEW) {
+			p2p_dbg(p2p,
+				"No common channels - force deferred flow");
+			auto_accept = 0;
+		}
+
+		if (((remote_conncap & P2PS_SETUP_GROUP_OWNER) ||
+		     msg.persistent_dev) && msg.operating_channel) {
+			struct p2p_channels intersect;
+
+			/* there are cases that only the operating channel is
+			 * provided. This requires saving the channel as the
+			 * support channel list, and verifying that it is
+			 * supported.
+			 */
+			if (dev->channels.reg_classes == 0 ||
+			    !p2p_channels_includes(&dev->channels,
+						   msg.operating_channel[3],
+						   msg.operating_channel[4])) {
+				struct p2p_channels *ch = &dev->channels;
+
+				os_memset(ch, 0, sizeof(*ch));
+				ch->reg_class[0].reg_class =
+					msg.operating_channel[3];
+				ch->reg_class[0].channel[0] =
+					msg.operating_channel[4];
+				ch->reg_class[0].channels = 1;
+				ch->reg_classes = 1;
+			}
+
+			p2p_channels_intersect(&p2p->channels, &dev->channels,
+					       &intersect);
+
+			if (intersect.reg_classes == 0) {
+				p2p_dbg(p2p,
+					"No common channels - force deferred flow");
+				auto_accept = 0;
+			}
+		}
+
 		if (auto_accept || reject != P2P_SC_SUCCESS) {
 			struct p2ps_provision *tmp;
 
@@ -857,10 +899,36 @@  void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
 			"Incompatible P2PS feature capability CPT bitmask");
 		reject =
 			P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
+	} else if ((remote_conncap & (P2PS_SETUP_NEW | P2PS_SETUP_CLIENT) ||
+		    msg.persistent_dev) &&
+		   msg.channel_list && msg.channel_list_len &&
+		   conncap != P2PS_SETUP_NEW &&
+		   (p2p_peer_channels_check(p2p, &p2p->channels, dev,
+					    msg.channel_list,
+					    msg.channel_list_len) < 0)) {
+		p2p_dbg(p2p,
+			"No common channels in Follow-On Provision Discovery Request");
+		reject = P2P_SC_FAIL_NO_COMMON_CHANNELS;
 	} else {
 		reject = P2P_SC_SUCCESS;
 	}
 
+	dev->oper_freq = 0;
+	if (reject == P2P_SC_SUCCESS ||
+	    reject == P2P_SC_SUCCESS_DEFERRED) {
+		if (msg.operating_channel)
+			dev->oper_freq =
+				p2p_channel_to_freq(msg.operating_channel[3],
+						    msg.operating_channel[4]);
+
+		if (conncap & P2PS_SETUP_GROUP_OWNER) {
+			u8 tmp;
+
+			if (p2p_go_select_channel(p2p, dev, &tmp) < 0)
+				reject = P2P_SC_FAIL_NO_COMMON_CHANNELS;
+		}
+	}
+
 	p2p->p2ps_prov->status = reject;
 	p2p->p2ps_prov->conncap = conncap;