Browse Source

P2P: Skip duplicated provision discovery on join

If p2p_prov_disc join command is used prior to p2p_connect join,
skip the duplicated provision discovery exchange.

Signed-hostap: Jithu Jance <jithu@broadcom.com>
Jithu Jance 13 years ago
parent
commit
ec437d9e74
5 changed files with 98 additions and 0 deletions
  1. 28 0
      src/p2p/p2p.c
  2. 22 0
      src/p2p/p2p.h
  3. 8 0
      src/p2p/p2p_i.h
  4. 7 0
      src/p2p/p2p_pd.c
  5. 33 0
      wpa_supplicant/p2p_supplicant.c

+ 28 - 0
src/p2p/p2p.c

@@ -114,6 +114,34 @@ static const char * p2p_state_txt(int state)
 }
 
 
+u16 p2p_get_provisioning_info(struct p2p_data *p2p, const u8 *addr)
+{
+	struct p2p_device *dev = NULL;
+
+	if (!addr || !p2p)
+		return 0;
+
+	dev = p2p_get_device(p2p, addr);
+	if (dev)
+		return dev->wps_prov_info;
+	else
+		return 0;
+}
+
+
+void p2p_clear_provisioning_info(struct p2p_data *p2p, const u8 *iface_addr)
+{
+	struct p2p_device *dev = NULL;
+
+	if (!iface_addr || !p2p)
+		return;
+
+	dev = p2p_get_device_interface(p2p, iface_addr);
+	if (dev)
+		dev->wps_prov_info = 0;
+}
+
+
 void p2p_set_state(struct p2p_data *p2p, int new_state)
 {
 	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: State %s -> %s",

+ 22 - 0
src/p2p/p2p.h

@@ -1035,6 +1035,28 @@ void p2p_wps_success_cb(struct p2p_data *p2p, const u8 *mac_addr);
  */
 void p2p_group_formation_failed(struct p2p_data *p2p);
 
+/**
+ * p2p_get_provisioning_info - Get any stored provisioning info
+ * @p2p: P2P module context from p2p_init()
+ * @addr: Peer P2P Device Address
+ * Returns: WPS provisioning information (WPS config method) or 0 if no
+ * information is available
+ *
+ * This function is used to retrieve stored WPS provisioning info for the given
+ * peer.
+ */
+u16 p2p_get_provisioning_info(struct p2p_data *p2p, const u8 *addr);
+
+/**
+ * p2p_clear_provisioning_info - Clear any stored provisioning info
+ * @p2p: P2P module context from p2p_init()
+ * @iface_addr: Peer P2P Interface Address
+ *
+ * This function is used to clear stored WPS provisioning info for the given
+ * peer.
+ */
+void p2p_clear_provisioning_info(struct p2p_data *p2p, const u8 *iface_addr);
+
 
 /* Event notifications from lower layer driver operations */
 

+ 8 - 0
src/p2p/p2p_i.h

@@ -73,6 +73,14 @@ struct p2p_device {
 	 */
 	u16 req_config_methods;
 
+	/**
+	 * wps_prov_info - Stored provisioning WPS config method
+	 *
+	 * This is used to store pending WPS config method between Provisioning
+	 * Discovery and connection to a running group.
+	 */
+	u16 wps_prov_info;
+
 #define P2P_DEV_PROBE_REQ_ONLY BIT(0)
 #define P2P_DEV_REPORTED BIT(1)
 #define P2P_DEV_NOT_YET_READY BIT(2)

+ 7 - 0
src/p2p/p2p_pd.c

@@ -267,6 +267,10 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
 			MAC2STR(sa));
 		dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
 	}
+
+	/* Store the provisioning info */
+	dev->wps_prov_info = msg.wps_config_methods;
+
 	p2p_parse_free(&msg);
 
 out:
@@ -352,6 +356,9 @@ int p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr,
 	if (config_methods == 0)
 		return -1;
 
+	/* Reset provisioning info */
+	dev->wps_prov_info = 0;
+
 	dev->req_config_methods = config_methods;
 	if (join)
 		dev->flags |= P2P_DEV_PD_FOR_JOIN;

+ 33 - 0
wpa_supplicant/p2p_supplicant.c

@@ -2296,6 +2296,14 @@ void wpas_p2p_deinit(struct wpa_supplicant *wpa_s)
 {
 	if (wpa_s->driver && wpa_s->drv_priv)
 		wpa_drv_probe_req_report(wpa_s, 0);
+
+	if (wpa_s->go_params) {
+		/* Clear any stored provisioning info */
+		p2p_clear_provisioning_info(
+			wpa_s->global->p2p,
+			wpa_s->go_params->peer_interface_addr);
+	}
+
 	os_free(wpa_s->go_params);
 	wpa_s->go_params = NULL;
 	eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL);
@@ -2505,6 +2513,21 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
 			break;
 		}
 
+		if ((p2p_get_provisioning_info(wpa_s->global->p2p,
+					       wpa_s->pending_join_dev_addr) ==
+		     method)) {
+			/*
+			 * We have already performed provision discovery for
+			 * joining the group. Proceed directly to join
+			 * operation without duplicated provision discovery. */
+			wpa_printf(MSG_DEBUG, "P2P: Provisioning discovery "
+				   "with " MACSTR " already done - proceed to "
+				   "join",
+				   MAC2STR(wpa_s->pending_join_dev_addr));
+			wpa_s->pending_pd_before_join = 0;
+			goto start;
+		}
+
 		if (p2p_prov_disc_req(wpa_s->global->p2p,
 				      wpa_s->pending_join_dev_addr, method, 1)
 		    < 0) {
@@ -3258,6 +3281,9 @@ void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
 		return;
 	}
 
+	/* Clear any stored provisioning info */
+	p2p_clear_provisioning_info(wpa_s->global->p2p, peer_addr);
+
 	eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->parent,
 			     NULL);
 	if (wpa_s->global->p2p)
@@ -3276,6 +3302,13 @@ void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s,
 			   "provisioning not in progress");
 		return;
 	}
+
+	if (wpa_s->go_params) {
+		p2p_clear_provisioning_info(
+			wpa_s->global->p2p,
+			wpa_s->go_params->peer_interface_addr);
+	}
+
 	wpas_notify_p2p_wps_failed(wpa_s, fail);
 }