P2P: Inviting a p2p device from already running persistent p2p go

Message ID 20120205095414.GB2180@w1.fi
State Accepted
Commit c427ac9211745a80c33d098dc8adc26fb9acd52c
Headers show

Commit Message

Jouni Malinen Feb. 5, 2012, 9:54 a.m.
On Wed, Feb 01, 2012 at 04:37:36AM -0800, Neeraj Kumar Garg wrote:
> 1. In the receive path of persistent invitation, supplicant code already checks for an already running group. So in that way, it makes more sense to check already running group in persistent= command for transmit case too.

Those are quite different cases. In the case we receive an Invitation
Request, wpa_supplicant has to answer it without external input to the
decision and because of that, the check for running group is needed.
This is not the case if we are sending an invitation.

> 2. We have to use either group= or persistent= command to find out if we are already running a persistent group. Lets say we use p2p_invite peer=xx group=xxx persistent=x command. [Doing automatically without persistent= will be difficult as we might have multiple entries in conf file with same go_dev_addr but different ssid]. For this we have to add the complete code of persistent verification from persistent invite to group invite.

I don't follow the logic here.

> 3. Logic is since an application want to do a persistent invite, we can make persistent invite to find out if the group is already running or not. The alternative logic is since group is already running, should the application do a persistent invite or a normal invite. I think both weighs equal in this aspect.

Use of wpas_p2p_invite() to send an invitation for an already running
group is misuse of the designed interfaces and results in incorrect
Invitation Request (incorrect operating channel information).

If I've understood your use case correctly, the only difference that
you want to see is in setting the Invitation Type in the Invitation
Flags attribute to 1 if a GO is running a persistent group and is about
to invite a peer that has previously connected to the persistent group.
This can be done automatically. Though, please note that this may result
in issues if the peer has already dropped all information of the
persistent group and in such a case, would just reject the invitation
with "Fail; unknown P2P Group".

As such, it could be safer to just make the "peer case" work in the way
that if it detects that an Invitation Request was received for an
already running persistent group for which there are stored credentials,
those credentials would be used automatically instead of WPS

Please take a look at the following patch that shows how the persistent
group case can be checked automatically as part of "p2p_invite
group=<ifname> peer=<peer addr>". Would this address your use case?


diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 88981d4..6a3223e 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -3053,7 +3053,7 @@  static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
 		return pos - buf;
 	pos += res;
-	ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr);
+	ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
 	if (ssid) {
 		res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
 		if (res < 0 || res >= end - pos)
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index a6298a7..1b66bdd 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -3707,6 +3707,7 @@  int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
 	enum p2p_invite_role role;
 	u8 *bssid = NULL;
 	struct wpa_ssid *ssid;
+	int persistent;
 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
 		if (os_strcmp(wpa_s->ifname, ifname) == 0)
@@ -3724,6 +3725,10 @@  int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
 		return -1;
+	persistent = ssid->p2p_persistent_group &&
+		wpas_p2p_get_persistent(wpa_s->parent, peer_addr,
+					ssid->ssid, ssid->ssid_len);
 	if (ssid->mode == WPAS_MODE_P2P_GO) {
 		bssid = wpa_s->own_addr;
@@ -3746,14 +3751,14 @@  int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
 	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
 		return wpa_drv_p2p_invite(wpa_s, peer_addr, role, bssid,
 					  ssid->ssid, ssid->ssid_len,
-					  go_dev_addr, 0);
+					  go_dev_addr, persistent);
 	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
 		return -1;
 	return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
 			  ssid->ssid, ssid->ssid_len, wpa_s->assoc_freq,
-			  go_dev_addr, 0);
+			  go_dev_addr, persistent);
@@ -4353,7 +4358,8 @@  void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s,
 struct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *wpa_s,
-					  const u8 *addr)
+					  const u8 *addr, const u8 *ssid,
+					  size_t ssid_len)
 	struct wpa_ssid *s;
 	size_t i;
@@ -4361,6 +4367,10 @@  struct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *wpa_s,
 	for (s = wpa_s->conf->ssid; s; s = s->next) {
 		if (s->disabled != 2)
+		if (ssid &&
+		    (ssid_len != s->ssid_len ||
+		     os_memcmp(ssid, s->ssid, ssid_len) != 0))
+			continue;
 		if (os_memcmp(s->bssid, addr, ETH_ALEN) == 0)
 			return s; /* peer is GO in the persistent group */
 		if (s->mode != WPAS_MODE_P2P_GO || s->p2p_client_list == NULL)
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 605741d..599ff3f 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -133,7 +133,8 @@  int wpas_p2p_in_progress(struct wpa_supplicant *wpa_s);
 void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s,
 			      struct wpa_ssid *ssid);
 struct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *wpa_s,
-					  const u8 *addr);
+					  const u8 *addr, const u8 *ssid,
+					  size_t ssid_len);
 void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
 				       const u8 *addr);