[PATCH 2/2] P2P: Update to D-Bus network object semantics during p2p group formation

Sane, Jayant jayant.sane at intel.com
Tue May 24 19:32:16 EDT 2011


Changes to not emit network objects during p2p group formation
since such network objects can confuse certain apps. Instead a
persistent group object is created to allow apps to keep track
of persistent groups. Persistent group objects only represent
the info needed to recreate the group.
Also fixes a minor bug in the handling of persistent group
objects during WPS operations.

Signed-off-by: Jayant Sane <jayant.sane at intel.com>
---
Note: This patch, along with the previous one in this set,  applies on top of
"0011-DBus-add-support-for-P2P-primitives.patch" being maintained at
http://johannes.sipsolutions.net/patches/hostap/p2p-dbus-9/


 wpa_supplicant/dbus/dbus_new.c              |  261 +++++++++++++++++++++++++++
 wpa_supplicant/dbus/dbus_new.h              |   24 +++
 wpa_supplicant/dbus/dbus_new_handlers.c     |    5 +-
 wpa_supplicant/dbus/dbus_new_handlers_p2p.c |   89 +++++++++
 wpa_supplicant/dbus/dbus_new_handlers_p2p.h |    9 +
 wpa_supplicant/notify.c                     |   18 ++-
 wpa_supplicant/notify.h                     |    2 +
 wpa_supplicant/p2p_supplicant.c             |   26 ++-
 wpa_supplicant/wpa_supplicant_i.h           |   11 ++
 wpa_supplicant/wps_supplicant.c             |   16 ++-
 10 files changed, 448 insertions(+), 13 deletions(-)

diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 3c3d268..433247f 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -1269,6 +1269,104 @@ error:
 	dbus_message_unref(msg);
 }
 
+/**
+ * wpas_dbus_signal_persistent_group - Send a persistent group related
+ *	event signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @id: new persistent group id
+ * @sig_name: signal name - PersistentGroupAdded, PersistentGroupRemoved
+ * @properties: determines if add second argument with object properties
+ *
+ * Notify listeners about event related with persistent group
+ */
+static void wpas_dbus_signal_persistent_group(struct wpa_supplicant *wpa_s,
+				     int id, const char *sig_name,
+				     int properties)
+{
+	struct wpas_dbus_priv *iface;
+	DBusMessage *msg;
+	DBusMessageIter iter, iter_dict;
+	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
+
+	iface = wpa_s->global->dbus;
+
+	/* Do nothing if the control interface is not turned on */
+	if (iface == NULL)
+		return;
+
+	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
+		    wpa_s->dbus_new_path, id);
+
+	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+				      sig_name);
+	if (msg == NULL)
+		return;
+
+	dbus_message_iter_init_append(msg, &iter);
+	path = pgrp_obj_path;
+	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+					    &path))
+		goto err;
+
+	if (properties) {
+		if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
+			goto err;
+
+		wpa_dbus_get_object_properties(iface, pgrp_obj_path,
+					       WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP,
+					       &iter_dict);
+
+		if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
+			goto err;
+	}
+
+	dbus_connection_send(iface->con, msg, NULL);
+
+	dbus_message_unref(msg);
+	return;
+
+err:
+	wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+	dbus_message_unref(msg);
+}
+
+
+/**
+ * wpas_dbus_signal_persistent_group_added - Send a persistent_group
+ *	added signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @id: new persistent group id
+ *
+ * Notify listeners about adding new persistent group
+ */
+static void wpas_dbus_signal_persistent_group_added(
+		struct wpa_supplicant *wpa_s,
+		int id)
+{
+	wpas_dbus_signal_persistent_group(wpa_s, id,
+						"PersistentGroupAdded",
+						TRUE);
+}
+
+/**
+ * wpas_dbus_signal_persistent_group_removed - Send a persistent_group
+ *	removed signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @id: persistent group id
+ *
+ * Notify listeners about removing a persistent group
+ */
+static void wpas_dbus_signal_persistent_group_removed(
+		struct wpa_supplicant *wpa_s,
+		int id)
+{
+	wpas_dbus_signal_persistent_group(wpa_s, id,
+						"PersistentGroupRemoved",
+						TRUE);
+}
+
 #endif /*CONFIG_P2P*/
 
 /**
@@ -1641,6 +1739,14 @@ int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
 	struct network_handler_args *arg;
 	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
 
+	/*
+	 * If its a persistent group register it likewise.
+	 * This is to handle cases where an i/f is being initialized with a
+	 * list of networks read from config.
+	 */
+	if (ssid->disabled == 2 || ssid->p2p_persistent_group)
+		return wpas_dbus_register_persistent_group(wpa_s, ssid);
+
 	/* Do nothing if the control interface is not turned on */
 	if (wpa_s == NULL || wpa_s->global == NULL)
 		return 0;
@@ -1703,6 +1809,13 @@ int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
 	struct wpas_dbus_priv *ctrl_iface;
 	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
 	int ret;
+	struct wpa_ssid *ssid;
+
+	ssid = wpa_config_get_network(wpa_s->conf, nid);
+
+	/* If its a persistent group unregister it likewise */
+	if (ssid->disabled == 2 || ssid->p2p_persistent_group)
+		return wpas_dbus_unregister_persistent_group(wpa_s, nid);
 
 	/* Do nothing if the control interface is not turned on */
 	if (wpa_s == NULL || wpa_s->global == NULL ||
@@ -2232,6 +2345,10 @@ static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
 	  (WPADBusPropertyAccessor) wpas_dbus_getter_p2p_peergo,
 	  R
 	},
+	{ "PersistentGroups", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_persistent_groups,
+	  NULL, R
+	},
 #endif /* CONFIG_P2P */
 	{ NULL, NULL, NULL, NULL, NULL, 0 }
 };
@@ -2428,6 +2545,13 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
 		  END_ARGS
 	  }
 	},
+	{ "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+	  {
+		  { "path", "o", ARG_OUT },
+		  { "properties", "a{sv}", ARG_OUT },
+		  END_ARGS
+	  }
+	},
 #endif /* CONFIG_P2P */
 	{ NULL, NULL, { END_ARGS } }
 };
@@ -2940,4 +3064,141 @@ void wpas_dbus_unregister_p2p_groupmember(struct wpa_supplicant *wpa_s,
 
 	wpa_dbus_unregister_object_per_iface(ctrl_iface, groupmember_obj_path);
 }
+
+static const struct wpa_dbus_property_desc
+			wpas_dbus_persistent_group_properties[] = {
+	{ "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
+	  (WPADBusPropertyAccessor)
+		wpas_dbus_getter_persistent_group_properties,
+	  NULL,
+	  R
+	},
+	{ NULL, NULL, NULL, NULL, NULL, 0 }
+};
+
+/* No signals intended for persistent group objects */
+
+/**
+ * wpas_dbus_register_persistent_group - Register a configured(saved)
+ *	persistent group with dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @ssid: persistent group (still represented as a network within wpa)
+ *	  configuration data
+ * Returns: 0 on success, -1 on failure
+ *
+ * Registers persistent group representing object with dbus
+ */
+int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
+			       struct wpa_ssid *ssid)
+{
+	struct wpas_dbus_priv *ctrl_iface;
+	struct wpa_dbus_object_desc *obj_desc;
+	struct network_handler_args *arg;
+	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+
+	/* Do nothing if the control interface is not turned on */
+	if (wpa_s == NULL || wpa_s->global == NULL)
+		return 0;
+
+	/* Make sure ssid is a persistent group */
+	if (ssid->disabled != 2 && !ssid->p2p_persistent_group)
+		return -1; /* should we return w/o complaining? */
+
+	ctrl_iface = wpa_s->global->dbus;
+	if (ctrl_iface == NULL)
+		return 0;
+
+	/*
+	 * Intentionally not coming up with different numbering scheme
+	 * for persistent groups.
+	 */
+	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
+		    wpa_s->dbus_new_path, ssid->id);
+
+	wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'",
+		   pgrp_obj_path);
+	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
+	if (!obj_desc) {
+		wpa_printf(MSG_ERROR, "Not enough memory "
+			   "to create object description");
+		goto err;
+	}
+
+	/*
+	 * Reusing the same context structure as that for networks
+	 * since these are represented using same data structure.
+	 */
+	/* allocate memory for handlers arguments */
+	arg = os_zalloc(sizeof(struct network_handler_args));
+	if (!arg) {
+		wpa_printf(MSG_ERROR, "Not enough memory "
+			   "to create arguments for method");
+		goto err;
+	}
+
+	arg->wpa_s = wpa_s;
+	arg->ssid = ssid;
+
+	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
+			   wpas_dbus_persistent_group_properties,
+			   NULL);
+
+	if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path,
+					       wpa_s->ifname, obj_desc))
+		goto err;
+
+	wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id);
+
+	return 0;
+
+err:
+	free_dbus_object_desc(obj_desc);
+	return -1;
+}
+
+
+/**
+ * wpas_dbus_unregister_persistent_group - Unregister a persistent_group
+ *	from dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @nid: network id
+ * Returns: 0 on success, -1 on failure
+ *
+ * Unregisters persistent group representing object from dbus
+ *
+ * NOTE: There is a slight issue with the semantics here. While the
+ * implementation simply means the persistent group is unloaded from memory,
+ * it should not get interpreted as the group is actually being erased/removed
+ * from persistent storage as well.
+ */
+int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
+						int nid)
+{
+	struct wpas_dbus_priv *ctrl_iface;
+	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+	int ret;
+
+	/* Do nothing if the control interface is not turned on */
+	if (wpa_s == NULL || wpa_s->global == NULL ||
+	    wpa_s->dbus_new_path == NULL)
+		return 0;
+	ctrl_iface = wpa_s->global->dbus;
+	if (ctrl_iface == NULL)
+		return 0;
+
+	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
+		    wpa_s->dbus_new_path, nid);
+
+	wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'",
+		   pgrp_obj_path);
+	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path);
+
+	if (!ret)
+		wpas_dbus_signal_persistent_group_removed(wpa_s, nid);
+
+	return ret;
+}
+
 #endif /* CONFIG_P2P */
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index e8376fe..8b5e831 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -72,6 +72,14 @@ enum wpas_dbus_bss_prop {
 #define WPAS_DBUS_NEW_P2P_GROUPS_PART	"Groups"
 #define	WPAS_DBUS_NEW_IFACE_P2P_GROUP WPAS_DBUS_NEW_INTERFACE ".Group"
 
+/*
+ * Different dbus object for persistent groups so they dont get confused
+ * with regular (configured) network objects.
+ */
+#define WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "PersistentGroups"
+#define WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP \
+	WPAS_DBUS_NEW_INTERFACE ".PersistentGroup"
+
 #define WPAS_DBUS_NEW_P2P_PEERS_PART	"Peers"
 #define	WPAS_DBUS_NEW_IFACE_P2P_PEER WPAS_DBUS_NEW_INTERFACE ".Peer"
 
@@ -170,6 +178,10 @@ void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
 void wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s, int status);
 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
 				    const struct wpa_ssid *ssid);
+int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
+			       struct wpa_ssid *ssid);
+int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
+						int nid);
 void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s,
 					    int status, const u8 *bssid);
 void wpas_dbus_register_p2p_groupmember(struct wpa_supplicant *wpa_s,
@@ -344,6 +356,18 @@ wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
 {
 }
 
+static inline int wpas_dbus_register_persistent_group(
+			struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+	return 0;
+}
+
+static inline int wpas_dbus_unregister_persistent_group(
+			struct wpa_supplicant *wpa_s, int nid)
+{
+	return 0;
+}
+
 static inline void
 wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s, int status)
 {
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index 4336a3a..ac8700e 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -2508,7 +2508,8 @@ DBusMessage * wpas_dbus_getter_networks(DBusMessage *message,
 	}
 
 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
-		num++;
+		if (!network_is_persistent_group(ssid))
+			num++;
 
 	paths = os_zalloc(num * sizeof(char *));
 	if (!paths) {
@@ -2518,6 +2519,8 @@ DBusMessage * wpas_dbus_getter_networks(DBusMessage *message,
 
 	/* Loop through configured networks and append object path of each */
 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+		if (network_is_persistent_group(ssid))
+			continue;
 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
 		if (paths[i] == NULL) {
 			reply = dbus_message_new_error(message,
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index 21fe7e6..24a6a9f 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -1206,6 +1206,95 @@ DBusMessage *wpas_dbus_getter_p2p_peer_ies(DBusMessage * message,
 }
 
 
+/******************************************************************/
+
+/**
+ * wpas_dbus_getter_persistent_groups - Get array of peristent group objects
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: a dbus message containing an array of all persistent group
+ * dbus object paths.
+ *
+ * Getter for "Networks" property.
+ */
+DBusMessage * wpas_dbus_getter_persistent_groups(DBusMessage *message,
+					struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	struct wpa_ssid *ssid;
+	char **paths;
+	unsigned int i = 0, num = 0;
+
+	if (wpa_s->conf == NULL) {
+		wpa_printf(MSG_ERROR, "wpas_dbus_getter_persistent_groups[dbus]: "
+			   "An error occurred getting persistent groups list.");
+		return wpas_dbus_error_unknown_error(message, NULL);
+	}
+
+	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
+		if (network_is_persistent_group(ssid))
+			num++;
+
+	paths = os_zalloc(num * sizeof(char *));
+	if (!paths) {
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+	}
+
+	/* Loop through configured networks and append object path of each */
+	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+		if (!network_is_persistent_group(ssid))
+			continue;
+		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
+		if (paths[i] == NULL) {
+			reply = dbus_message_new_error(message,
+				 			DBUS_ERROR_NO_MEMORY,
+							NULL);
+			goto out;
+		}
+		/* Construct the object path for this network. */
+		os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
+			    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
+			    wpa_s->dbus_new_path, ssid->id);
+	}
+
+	reply = wpas_dbus_simple_array_property_getter(message,
+						       DBUS_TYPE_OBJECT_PATH,
+						       paths, num);
+
+out:
+	while (i)
+		os_free(paths[--i]);
+	os_free(paths);
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
+ *	group
+ * @message: Pointer to incoming dbus message
+ * @net: wpa_supplicant structure for a network interface and
+ * wpa_ssid structure for a configured persistent group (internally network)
+ * Returns: DBus message with network properties or DBus error on failure
+ *
+ * Getter for "Properties" property of a persistent group.
+ */
+DBusMessage *wpas_dbus_getter_persistent_group_properties(
+	DBusMessage *message, struct network_handler_args *net)
+{
+
+	/*
+	 * Leveraging the fact that persistent group object is still
+	 * represented in same manner as network within.
+	 */
+	return wpas_dbus_getter_network_properties(message, net);
+}
+
+
+
+/******************************************************************/
+
 /*
  * Group object properties accessor methods
  */
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.h b/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
index d911037..37a5c15 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
@@ -139,4 +139,13 @@ DBusMessage *wpas_dbus_setter_p2p_group_properties(
 		DBusMessage *message,
 		struct wpa_supplicant *wpa_s);
 
+/*
+ * P2P Persistent Group properties
+ */
+
+DBusMessage * wpas_dbus_getter_persistent_groups(DBusMessage *message,
+					struct wpa_supplicant *wpa_s);
+DBusMessage *wpas_dbus_getter_persistent_group_properties(
+	DBusMessage *message, struct network_handler_args *net);
+
 #endif /* CTRL_IFACE_DBUS_NEW_HANDLERS_P2P_H */
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 7741366..ac213fa 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -206,14 +206,28 @@ void wpas_notify_wps_event_success(struct wpa_supplicant *wpa_s)
 void wpas_notify_network_added(struct wpa_supplicant *wpa_s,
 			       struct wpa_ssid *ssid)
 {
-	wpas_dbus_register_network(wpa_s, ssid);
+	/*
+	 * Networks objects created during any P2P activities should not be
+	 * exposed out. They might/will confuse certain non-P2P aware
+	 * applications since these network objects wont behave like
+	 * regular ones.
+	 */
+	if (wpa_s->global->p2p_group_formation != wpa_s)
+		wpas_dbus_register_network(wpa_s, ssid);
+}
+
+void wpas_notify_persistent_group_added(struct wpa_supplicant *wpa_s,
+			       struct wpa_ssid *ssid)
+{
+	wpas_dbus_register_persistent_group(wpa_s, ssid);
 }
 
 
 void wpas_notify_network_removed(struct wpa_supplicant *wpa_s,
 				 struct wpa_ssid *ssid)
 {
-	wpas_dbus_unregister_network(wpa_s, ssid->id);
+	if (wpa_s->global->p2p_group_formation != wpa_s)
+		wpas_dbus_unregister_network(wpa_s, ssid->id);
 }
 
 
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index 7bbce19..b622b31 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -115,4 +115,6 @@ void wpas_notify_p2p_group_started(struct wpa_supplicant *wpa_s,
 				   int client);
 void wpas_notify_ap_sta_deauthorized(struct wpa_supplicant *wpa_s,
 				     const u8 *sta);
+void wpas_notify_persistent_group_added(struct wpa_supplicant *wpa_s,
+			       struct wpa_ssid *ssid);
 #endif /* NOTIFY_H */
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index f0a144f..0fdce35 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -310,7 +310,14 @@ static void wpas_p2p_group_delete(struct wpa_supplicant *wpa_s)
 		int id = ssid->id;
 		if (ssid == wpa_s->current_ssid)
 			wpa_s->current_ssid = NULL;
-		wpas_notify_network_removed(wpa_s, ssid);
+		/*
+		 * Networks objects created during any P2P activities are not
+		 * exposed out as they might/will confuse certain non-P2P aware
+		 * applications since these network objects wont behave like
+		 * regular ones.
+		 * Likewise we dont send out network removed signals for such
+		 * network objects.
+		 */
 		wpa_config_remove_network(wpa_s->conf, id);
 		wpa_supplicant_clear_status(wpa_s);
 	} else {
@@ -382,7 +389,6 @@ static int wpas_p2p_persistent_group(struct wpa_supplicant *wpa_s,
 	return group_capab & P2P_GROUP_CAPAB_PERSISTENT_GROUP;
 }
 
-
 static int wpas_p2p_store_persistent_group(struct wpa_supplicant *wpa_s,
 					   struct wpa_ssid *ssid,
 					   const u8 *go_dev_addr)
@@ -393,7 +399,7 @@ static int wpas_p2p_store_persistent_group(struct wpa_supplicant *wpa_s,
 	wpa_printf(MSG_DEBUG, "P2P: Storing credentials for a persistent "
 		   "group (GO Dev Addr " MACSTR ")", MAC2STR(go_dev_addr));
 	for (s = wpa_s->conf->ssid; s; s = s->next) {
-		if (s->disabled == 2 &&
+		if ((s->disabled == 2) &&
 		    os_memcmp(go_dev_addr, s->bssid, ETH_ALEN) == 0 &&
 		    s->ssid_len == ssid->ssid_len &&
 		    os_memcmp(ssid->ssid, s->ssid, ssid->ssid_len) == 0)
@@ -415,7 +421,16 @@ static int wpas_p2p_store_persistent_group(struct wpa_supplicant *wpa_s,
 		s = wpa_config_add_network(wpa_s->conf);
 		if (s == NULL)
 			return -1;
-		wpas_notify_network_added(wpa_s, s);
+
+		/*
+		 * Instead of network_added we emit persistent_group_added
+		 * notification. Also to keep the defense checks in
+		 * persistent_group obj registration method, we set the
+		 * relevant flags in s to designate it as a persistent group.
+		 */
+		s->p2p_group = 1;
+		s->p2p_persistent_group = 1;
+		wpas_notify_persistent_group_added(wpa_s, s);
 		wpa_config_set_network_defaults(s);
 	}
 
@@ -919,7 +934,6 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s,
 	if (ssid == NULL)
 		return;
 
-	wpas_notify_network_added(wpa_s, ssid);
 	wpa_config_set_network_defaults(ssid);
 	ssid->temporary = 1;
 	ssid->p2p_group = 1;
@@ -3321,7 +3335,6 @@ static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
 	ssid = wpa_config_add_network(wpa_s->conf);
 	if (ssid == NULL)
 		return -1;
-	wpas_notify_network_added(wpa_s, ssid);
 	wpa_config_set_network_defaults(ssid);
 	ssid->temporary = 1;
 	ssid->proto = WPA_PROTO_RSN;
@@ -3330,7 +3343,6 @@ static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
 	ssid->key_mgmt = WPA_KEY_MGMT_PSK;
 	ssid->ssid = os_malloc(params->ssid_len);
 	if (ssid->ssid == NULL) {
-		wpas_notify_network_removed(wpa_s, ssid);
 		wpa_config_remove_network(wpa_s->conf, ssid->id);
 		return -1;
 	}
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index e01c81c..2dece52 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -634,4 +634,15 @@ void wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
 /* eap_register.c */
 int eap_register_methods(void);
 
+/**
+ * Utility method to tell of a given network is a persistent group
+ * @ssid: network object
+ *
+ * Return 1 if network is a persistent group, 0 otherwise.
+ */
+static inline int network_is_persistent_group(struct wpa_ssid *ssid)
+{
+	return ((ssid->disabled == 2) || ssid->p2p_persistent_group);
+}
+
 #endif /* WPA_SUPPLICANT_I_H */
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index 778ccaf..8ec278a 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -780,9 +780,19 @@ static void wpas_wps_reassoc(struct wpa_supplicant *wpa_s,
 	ssid = wpa_s->conf->ssid;
 	while (ssid) {
 		int was_disabled = ssid->disabled;
-		ssid->disabled = ssid != selected;
-		if (was_disabled != ssid->disabled)
-			wpas_notify_network_enabled_changed(wpa_s, ssid);
+		/*
+		 * In case the network object corresponds to a
+		 * persistent group then do not send out network
+		 * disabled signal.
+		 * This also fixes a bug that changed the disabled status of
+		 * persistent network objects from 2 to 1 when we connect to
+		 * some other network either infra or different group.
+		 */
+		if (was_disabled != 2) {
+			ssid->disabled = ssid != selected;
+			if (was_disabled != ssid->disabled)
+				wpas_notify_network_enabled_changed(wpa_s, ssid);
+		}
 		ssid = ssid->next;
 	}
 	wpa_s->disconnected = 0;
-- 
1.7.1




More information about the HostAP mailing list