Browse Source

P2P: Advertise Persistent Reconnect group capability

The persistent_reconnect configuration parameter was used to decide
whether to accept invitation to re-establish a persistent group.
However, this was not being advertised in the Group Capability bitmap.
Add the Persistent Reconnect bit based on this configuration to GO
Negotiation frames and Beacon/Probe Response frames from the GO.
Jouni Malinen 13 years ago
parent
commit
acc247b260
6 changed files with 70 additions and 17 deletions
  1. 28 10
      src/p2p/p2p.c
  2. 12 2
      src/p2p/p2p.h
  3. 14 3
      src/p2p/p2p_go_neg.c
  4. 4 1
      src/p2p/p2p_group.c
  5. 1 0
      src/p2p/p2p_i.h
  6. 11 1
      wpa_supplicant/p2p_supplicant.c

+ 28 - 10
src/p2p/p2p.c

@@ -1029,6 +1029,26 @@ static int p2p_prepare_channel(struct p2p_data *p2p, unsigned int force_freq)
 }
 
 
+static void p2p_set_dev_persistent(struct p2p_device *dev,
+				   int persistent_group)
+{
+	switch (persistent_group) {
+	case 0:
+		dev->flags &= ~(P2P_DEV_PREFER_PERSISTENT_GROUP |
+				P2P_DEV_PREFER_PERSISTENT_RECONN);
+		break;
+	case 1:
+		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP;
+		dev->flags &= ~P2P_DEV_PREFER_PERSISTENT_RECONN;
+		break;
+	case 2:
+		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP |
+			P2P_DEV_PREFER_PERSISTENT_RECONN;
+		break;
+	}
+}
+
+
 int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
 		enum p2p_wps_method wps_method,
 		int go_intent, const u8 *own_interface_addr,
@@ -1086,10 +1106,7 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
 	dev->connect_reqs = 0;
 	dev->go_neg_req_sent = 0;
 	dev->go_state = UNKNOWN_GO;
-	if (persistent_group)
-		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP;
-	else
-		dev->flags &= ~P2P_DEV_PREFER_PERSISTENT_GROUP;
+	p2p_set_dev_persistent(dev, persistent_group);
 	p2p->go_intent = go_intent;
 	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
 
@@ -1159,10 +1176,7 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
 	dev->flags &= ~P2P_DEV_USER_REJECTED;
 	dev->go_neg_req_sent = 0;
 	dev->go_state = UNKNOWN_GO;
-	if (persistent_group)
-		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP;
-	else
-		dev->flags &= ~P2P_DEV_PREFER_PERSISTENT_GROUP;
+	p2p_set_dev_persistent(dev, persistent_group);
 	p2p->go_intent = go_intent;
 	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
 
@@ -1273,8 +1287,12 @@ void p2p_go_complete(struct p2p_data *p2p, struct p2p_device *peer)
 	os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, ETH_ALEN);
 	os_memcpy(res.peer_interface_addr, peer->intended_addr, ETH_ALEN);
 	res.wps_method = peer->wps_method;
-	if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP)
-		res.persistent_group = 1;
+	if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) {
+		if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN)
+			res.persistent_group = 2;
+		else
+			res.persistent_group = 1;
+	}
 
 	if (go) {
 		/* Setup AP mode for WPS provisioning */

+ 12 - 2
src/p2p/p2p.h

@@ -120,6 +120,9 @@ struct p2p_go_neg_results {
 
 	/**
 	 * persistent_group - Whether the group should be made persistent
+	 * 0 = not persistent
+	 * 1 = persistent group without persistent reconnect
+	 * 2 = persistent group with persistent reconnect
 	 */
 	int persistent_group;
 
@@ -846,7 +849,9 @@ int p2p_listen(struct p2p_data *p2p, unsigned int timeout);
  * @go_intent: Local GO intent value (1..15)
  * @own_interface_addr: Intended interface address to use with the group
  * @force_freq: The only allowed channel frequency in MHz or 0
- * @persistent_group: Whether to create a persistent group
+ * @persistent_group: Whether to create a persistent group (0 = no, 1 =
+ * persistent group without persistent reconnect, 2 = persistent group with
+ * persistent reconnect)
  * Returns: 0 on success, -1 on failure
  */
 int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
@@ -862,7 +867,9 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
  * @go_intent: Local GO intent value (1..15)
  * @own_interface_addr: Intended interface address to use with the group
  * @force_freq: The only allowed channel frequency in MHz or 0
- * @persistent_group: Whether to create a persistent group
+ * @persistent_group: Whether to create a persistent group (0 = no, 1 =
+ * persistent group without persistent reconnect, 2 = persistent group with
+ * persistent reconnect)
  * Returns: 0 on success, -1 on failure
  *
  * This is like p2p_connect(), but the actual group negotiation is not
@@ -1164,6 +1171,9 @@ struct p2p_group;
 struct p2p_group_config {
 	/**
 	 * persistent_group - Whether the group is persistent
+	 * 0 = not a persistent group
+	 * 1 = persistent group without persistent reconnect
+	 * 2 = persistent group with persistent reconnect
 	 */
 	int persistent_group;
 

+ 14 - 3
src/p2p/p2p_go_neg.c

@@ -152,8 +152,11 @@ static struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p,
 
 	len = p2p_buf_add_ie_hdr(buf);
 	group_capab = 0;
-	if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP)
+	if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) {
 		group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
+		if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN)
+			group_capab |= P2P_GROUP_CAPAB_PERSISTENT_RECONN;
+	}
 	if (p2p->cross_connect)
 		group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
 	if (p2p->cfg->p2p_intra_bss)
@@ -242,8 +245,12 @@ static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p,
 	p2p_buf_add_status(buf, status);
 	group_capab = 0;
 	if (peer && peer->go_state == LOCAL_GO) {
-		if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP)
+		if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) {
 			group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
+			if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN)
+				group_capab |=
+					P2P_GROUP_CAPAB_PERSISTENT_RECONN;
+		}
 		if (p2p->cross_connect)
 			group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
 		if (p2p->cfg->p2p_intra_bss)
@@ -673,8 +680,12 @@ static struct wpabuf * p2p_build_go_neg_conf(struct p2p_data *p2p,
 	p2p_buf_add_status(buf, status);
 	group_capab = 0;
 	if (peer->go_state == LOCAL_GO) {
-		if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP)
+		if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) {
 			group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
+			if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN)
+				group_capab |=
+					P2P_GROUP_CAPAB_PERSISTENT_RECONN;
+		}
 		if (p2p->cross_connect)
 			group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
 		if (p2p->cfg->p2p_intra_bss)

+ 4 - 1
src/p2p/p2p_group.c

@@ -147,8 +147,11 @@ static void p2p_group_add_common_ies(struct p2p_group *group,
 	dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
 	dev_capab |= P2P_DEV_CAPAB_INVITATION_PROCEDURE;
 	group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
-	if (group->cfg->persistent_group)
+	if (group->cfg->persistent_group) {
 		group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
+		if (group->cfg->persistent_group == 2)
+			group_capab |= P2P_GROUP_CAPAB_PERSISTENT_RECONN;
+	}
 	if (group->p2p->cfg->p2p_intra_bss)
 		group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
 	if (group->group_formation)

+ 1 - 0
src/p2p/p2p_i.h

@@ -89,6 +89,7 @@ struct p2p_device {
 #define P2P_DEV_FORCE_FREQ BIT(13)
 #define P2P_DEV_PD_FOR_JOIN BIT(14)
 #define P2P_DEV_REPORTED_ONCE BIT(15)
+#define P2P_DEV_PREFER_PERSISTENT_RECONN BIT(16)
 	unsigned int flags;
 
 	int status; /* enum p2p_status_code */

+ 11 - 1
wpa_supplicant/p2p_supplicant.c

@@ -756,6 +756,7 @@ static void wpas_p2p_clone_config(struct wpa_supplicant *dst,
 
 	d->p2p_group_idle = s->p2p_group_idle;
 	d->p2p_intra_bss = s->p2p_intra_bss;
+	d->persistent_reconnect = s->persistent_reconnect;
 }
 
 
@@ -2376,6 +2377,9 @@ static int wpas_p2p_start_go_neg(struct wpa_supplicant *wpa_s,
 				 int go_intent, const u8 *own_interface_addr,
 				 unsigned int force_freq, int persistent_group)
 {
+	if (persistent_group && wpa_s->conf->persistent_reconnect)
+		persistent_group = 2;
+
 	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
 		return wpa_drv_p2p_connect(wpa_s, peer_addr, wps_method,
 					   go_intent, own_interface_addr,
@@ -2394,6 +2398,9 @@ static int wpas_p2p_auth_go_neg(struct wpa_supplicant *wpa_s,
 				int go_intent, const u8 *own_interface_addr,
 				unsigned int force_freq, int persistent_group)
 {
+	if (persistent_group && wpa_s->conf->persistent_reconnect)
+		persistent_group = 2;
+
 	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
 		return -1;
 
@@ -3210,7 +3217,10 @@ struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
 	if (cfg == NULL)
 		return NULL;
 
-	cfg->persistent_group = persistent_group;
+	if (persistent_group && wpa_s->conf->persistent_reconnect)
+		cfg->persistent_group = 2;
+	else if (persistent_group)
+		cfg->persistent_group = 1;
 	os_memcpy(cfg->interface_addr, wpa_s->own_addr, ETH_ALEN);
 	if (wpa_s->max_stations &&
 	    wpa_s->max_stations < wpa_s->conf->max_num_sta)