[PATCH v2 12/14] P2P: Add P2P2 support for autogo and client join

Shivani Baranwal quic_shivbara at quicinc.com
Thu Jul 18 21:40:04 PDT 2024


Signed-off-by: Shivani Baranwal <quic_shivbara at quicinc.com>
---
 src/p2p/p2p.c                               |  16 ++-
 src/p2p/p2p.h                               |   4 +
 src/p2p/p2p_i.h                             |   5 +
 wpa_supplicant/ctrl_iface.c                 |   5 +-
 wpa_supplicant/dbus/dbus_new_handlers_p2p.c |   2 +-
 wpa_supplicant/p2p_supplicant.c             | 162 +++++++++++++++++++++++-----
 wpa_supplicant/p2p_supplicant.h             |   3 +-
 wpa_supplicant/wpa_supplicant_i.h           |   3 +
 8 files changed, 168 insertions(+), 32 deletions(-)

diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 8a89e29..a609dca 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -1867,6 +1867,12 @@ int p2p_go_params(struct p2p_data *p2p, struct p2p_go_neg_results *params)
 }
 
 
+void p2p_set_auto_go(struct p2p_data *p2p)
+{
+	p2p->auto_go = 1;
+}
+
+
 void p2p_go_complete(struct p2p_data *p2p, struct p2p_device *peer)
 {
 	struct p2p_go_neg_results res;
@@ -1958,9 +1964,13 @@ void p2p_go_complete(struct p2p_data *p2p, struct p2p_device *peer)
 
 		wpa_pasn_reset(peer->pasn);
 	}
-
-	p2p_set_state(p2p, P2P_PROVISIONING);
-	p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res);
+	if (p2p->auto_go && peer->p2p2) {
+		p2p->cfg->set_auto_go_pmk(p2p->cfg->cb_ctx, &res);
+		p2p->auto_go = 0;
+	} else {
+		p2p_set_state(p2p, P2P_PROVISIONING);
+		p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res);
+	}
 }
 
 
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 89c99ca..b52dbe1 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -934,6 +934,8 @@ struct p2p_config {
 	 */
 	void (*go_neg_completed)(void *ctx, struct p2p_go_neg_results *res);
 
+	void (*set_auto_go_pmk)(void *ctx, struct p2p_go_neg_results *res);
+
 	/**
 	 * sd_request - Callback on Service Discovery Request
 	 * @ctx: Callback context from cb_ctx
@@ -2135,6 +2137,8 @@ size_t p2p_scan_ie_buf_len(struct p2p_data *p2p);
  */
 int p2p_go_params(struct p2p_data *p2p, struct p2p_go_neg_results *params);
 
+void p2p_set_auto_go(struct p2p_data *p2p);
+
 /**
  * p2p_get_group_capab - Get Group Capability from P2P IE data
  * @p2p_ie: P2P IE(s) contents
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index 6dce2d8..80e1988 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -693,6 +693,11 @@ struct p2p_data {
 	 * invitation_resp - Invitation Response frame
 	 */
 	struct wpabuf *invitation_resp;
+
+	/**
+	 * Indicate that auto go is enabled for this device
+	 */
+	u8 auto_go;
 };
 
 /**
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 4cfff25..3f247a7 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -7219,6 +7219,7 @@ static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
 {
 	int freq = 0, persistent = 0, group_id = -1;
+	bool p2p2 = false;
 	bool allow_6ghz = false;
 	int vht = wpa_s->conf->p2p_go_vht;
 	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
@@ -7255,6 +7256,8 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
 			persistent = 1;
 		} else if (os_strcmp(token, "allow_6ghz") == 0) {
 			allow_6ghz = true;
+		} else if (os_strcmp(token, "p2p2") == 0) {
+			p2p2 = true;
 		} else if (os_strncmp(token, "go_bssid=", 9) == 0) {
 			if (hwaddr_aton(token + 9, go_bssid_buf))
 				return -1;
@@ -7306,7 +7309,7 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
 						     go_bssid);
 
 	return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
-				  max_oper_chwidth, he, edmg, allow_6ghz);
+				  max_oper_chwidth, he, edmg, allow_6ghz, p2p2);
 }
 
 
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index 76548d6..e9ae171 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -489,7 +489,7 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
 		}
 	} else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, freq2,
 				      ht40, vht, max_oper_chwidth, he, edmg,
-				      allow_6ghz))
+				      allow_6ghz, wpa_s->p2p2))
 		goto inv_args;
 
 out:
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 2a21842..7283719 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -1830,6 +1830,8 @@ static void wpas_start_gc(struct wpa_supplicant *wpa_s,
 	ssid->key_mgmt = WPA_KEY_MGMT_SAE;
 	ssid->pairwise_cipher = res->cipher;
 	ssid->group_cipher = res->cipher;
+	//FIMXE: Check if we need to update both wpa_s->conf and ssid
+	ssid->sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
 	wpa_s->conf->sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
 	ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
 	ssid->disabled = 0;
@@ -2608,6 +2610,44 @@ bool wpas_p2p_retry_limit_exceeded(struct wpa_supplicant *wpa_s)
 }
 
 
+static void wpas_set_auto_go_pmk(void *ctx, struct p2p_go_neg_results *params)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+	struct wpa_supplicant *ifs;
+	struct sta_info sta;
+	struct sae_data *sae;
+	struct hostapd_data *hapd;
+
+	dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
+			 radio_list) {
+		if (ifs->current_ssid &&
+		    ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
+			break;
+	}
+
+	if (ifs && ifs->ap_iface && params->p2p2 &&
+	    params->akmp == WPA_KEY_MGMT_SAE) {
+		hapd = ifs->ap_iface->bss[0];
+		memset(&sta, 0, sizeof(struct sta_info));
+		memcpy(sta.addr, params->peer_device_addr, ETH_ALEN);
+		sae = os_zalloc(sizeof(struct sae_data));
+		if (sae) {
+			sta.sae = sae;
+			memcpy(sta.sae->pmkid, params->pmkid, PMKID_LEN);
+			wpa_printf(MSG_DEBUG, "P2P: Adding PMK for peer: " MACSTR
+					" by autonomous go",
+					MAC2STR(params->peer_device_addr));
+			wpa_auth_pmksa_add_sae(hapd->wpa_auth,
+					       params->peer_device_addr,
+					       params->pmk, params->pmk_len,
+					       params->pmkid, WPA_KEY_MGMT_SAE);
+			sae_sme_send_external_auth_status(hapd, &sta, 0);
+			memset(&sta, 0, sizeof(struct sta_info));
+			os_free(sae);
+		}
+	}
+}
+
 static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
 {
 	struct wpa_supplicant *wpa_s = ctx;
@@ -4864,7 +4904,8 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
 					0);
 			} else if (response_done) {
 				wpas_p2p_group_add(wpa_s, 1, freq,
-						   0, 0, 0, 0, 0, 0, false);
+						   0, 0, 0, 0, 0, 0, false,
+						   wpa_s->p2p2);
 			}
 
 			if (passwd_id == DEV_PW_P2PS_DEFAULT) {
@@ -4988,7 +5029,8 @@ static int wpas_prov_disc_resp_cb(void *ctx)
 			NULL, NULL, 0);
 	} else {
 		wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0, 0, 0,
-				   is_p2p_allow_6ghz(wpa_s->global->p2p));
+				   is_p2p_allow_6ghz(wpa_s->global->p2p),
+				   wpa_s->p2p2);
 	}
 
 	return 1;
@@ -5338,6 +5380,7 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
 	p2p.send_action = wpas_send_action;
 	p2p.send_action_done = wpas_send_action_done;
 	p2p.go_neg_completed = wpas_go_neg_completed;
+	p2p.set_auto_go_pmk = wpas_set_auto_go_pmk;
 	p2p.go_neg_req_rx = wpas_go_neg_req_rx;
 	p2p.dev_found = wpas_dev_found;
 	p2p.dev_lost = wpas_dev_lost;
@@ -5782,7 +5825,7 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
 	if (scan_res)
 		wpas_p2p_scan_res_handler(wpa_s, scan_res);
 
-	if (wpa_s->p2p_auto_pd) {
+	if (!wpa_s->p2p2 && wpa_s->p2p_auto_pd) {
 		int join = wpas_p2p_peer_go(wpa_s,
 					    wpa_s->pending_join_dev_addr);
 		if (join == 0 &&
@@ -5823,15 +5866,22 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
 		return;
 	}
 
-	if (wpa_s->p2p_auto_join) {
+	if (wpa_s->p2p2 || wpa_s->p2p_auto_join) {
 		int join = wpas_p2p_peer_go(wpa_s,
 					    wpa_s->pending_join_dev_addr);
-		if (join < 0) {
-			wpa_printf(MSG_DEBUG, "P2P: Peer was not found to be "
-				   "running a GO -> use GO Negotiation");
-			wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
-				       P2P_EVENT_FALLBACK_TO_GO_NEG
-				       "reason=peer-not-running-GO");
+		if (wpa_s->p2p2 || join < 0) {
+			if (join < 0) {
+				wpa_printf(MSG_DEBUG, "P2P: Peer was not found to be "
+					   "running a GO -> use GO Negotiation");
+				wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
+					       P2P_EVENT_FALLBACK_TO_GO_NEG
+					       "reason=peer-not-running-GO");
+			}
+
+			if (wpa_s->p2p2)
+				wpa_printf(MSG_DEBUG,
+					   "P2P2: Initiate Go Neg and provisioning "
+					   "using PASN Authentication");
 			wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr,
 					 wpa_s->p2p_pin, wpa_s->p2p_wps_method,
 					 wpa_s->p2p_persistent_group, 0, 0, 0,
@@ -5848,7 +5898,8 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
 					 NULL, 0,
 					 is_p2p_allow_6ghz(wpa_s->global->p2p),
 					 wpa_s->p2p2, wpa_s->p2p_bootstrap,
-					 NULL);
+					 wpa_s->pending_join_password_len ?
+					 wpa_s->pending_join_password : NULL);
 			return;
 		}
 
@@ -6002,7 +6053,7 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
 {
 	int ret;
 	struct wpa_driver_scan_params params;
-	struct wpabuf *wps_ie, *ies;
+	struct wpabuf *wps_ie = NULL, *ies;
 	size_t ielen;
 	int freqs[2] = { 0, 0 };
 	unsigned int bands;
@@ -6022,13 +6073,16 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
 		wpa_s->p2p_join_ssid_len = 0;
 	}
 
-	wpa_s->wps->dev.p2p = 1;
-	wps_ie = wps_build_probe_req_ie(DEV_PW_DEFAULT, &wpa_s->wps->dev,
-					wpa_s->wps->uuid, WPS_REQ_ENROLLEE, 0,
-					NULL);
-	if (wps_ie == NULL) {
-		wpas_p2p_scan_res_join(wpa_s, NULL);
-		return;
+	if (!wpa_s->p2p2) {
+		wpa_s->wps->dev.p2p = 1;
+		wps_ie = wps_build_probe_req_ie(DEV_PW_DEFAULT,
+						&wpa_s->wps->dev,
+						wpa_s->wps->uuid,
+						WPS_REQ_ENROLLEE, 0, NULL);
+		if (!wps_ie) {
+			wpas_p2p_scan_res_join(wpa_s, NULL);
+			return;
+		}
 	}
 
 	if (!freq) {
@@ -6050,14 +6104,21 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
 	}
 
 	ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
-	ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
-	if (ies == NULL) {
+
+	if (wps_ie)
+		ielen += wpabuf_len(wps_ie);
+
+	ies = wpabuf_alloc(ielen);
+	if (!ies) {
 		wpabuf_free(wps_ie);
 		wpas_p2p_scan_res_join(wpa_s, NULL);
 		return;
 	}
-	wpabuf_put_buf(ies, wps_ie);
-	wpabuf_free(wps_ie);
+
+	if (wps_ie) {
+		wpabuf_put_buf(ies, wps_ie);
+		wpabuf_free(wps_ie);
+	}
 
 	bands = wpas_get_bands(wpa_s, freqs);
 	p2p_scan_ie(wpa_s->global->p2p, ies, NULL, bands);
@@ -6167,7 +6228,16 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s, int freq,
 	os_memcpy(res.peer_device_addr, wpa_s->pending_join_dev_addr, ETH_ALEN);
 	os_memcpy(res.peer_interface_addr, wpa_s->pending_join_iface_addr,
 		  ETH_ALEN);
+	if (wpa_s->pending_join_password_len) {
+		res.akmp = WPA_KEY_MGMT_SAE;
+		res.password_len = wpa_s->pending_join_password_len;
+		os_memcpy(res.password, wpa_s->pending_join_password,
+			  res.password_len);
+	}
 	res.wps_method = wpa_s->pending_join_wps_method;
+	res.p2p2 = wpa_s->p2p2;
+	res.cipher = WPA_CIPHER_CCMP;
+
 	if (freq && ssid && ssid_len) {
 		res.freq = freq;
 		res.ssid_len = ssid_len;
@@ -6202,7 +6272,10 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s, int freq,
 		wpa_s->off_channel_freq = 0;
 		wpa_s->roc_waiting_drv_freq = 0;
 	}
-	wpas_start_wps_enrollee(group, &res);
+	if (res.p2p2)
+		wpas_start_gc(group, &res);
+	else
+		wpas_start_wps_enrollee(group, &res);
 
 	/*
 	 * Allow a longer timeout for join-a-running-group than normal 15
@@ -6485,12 +6558,41 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
 
 	if (join || auto_join) {
 		u8 iface_addr[ETH_ALEN], dev_addr[ETH_ALEN];
+		struct wpa_supplicant *ifs;
 		if (auth) {
 			wpa_printf(MSG_DEBUG, "P2P: Authorize invitation to "
 				   "connect a running group from " MACSTR,
 				   MAC2STR(peer_addr));
 			os_memcpy(wpa_s->p2p_auth_invite, peer_addr, ETH_ALEN);
-			return ret;
+
+			if (!wpa_s->p2p2)
+				return ret;
+
+			if (is_zero_ether_addr(wpa_s->pending_interface_addr)) {
+				wpa_printf(MSG_DEBUG, "P2P: Interface address Invalid");
+				return -1;
+			}
+
+			wpa_printf(MSG_DEBUG, "P2P: own interface address for "
+				   "authorizing join " MACSTR,
+				   MAC2STR(wpa_s->pending_interface_addr));
+
+			dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
+					 radio_list) {
+				if (ifs->current_ssid == NULL ||
+				    ifs->current_ssid->mode != WPAS_MODE_P2P_GO)
+					continue;
+
+				ssid = ifs->current_ssid;
+			}
+			p2p_set_auto_go(wpa_s->global->p2p);
+			return wpas_p2p_auth_go_neg(wpa_s, peer_addr,
+						    wps_method, 15,
+						    wpa_s->pending_interface_addr,
+						    force_freq,
+						    persistent_group, ssid,
+						    pref_freq, bootstrap,
+						    password);
 		}
 		os_memcpy(dev_addr, peer_addr, ETH_ALEN);
 		if (p2p_get_interface_addr(wpa_s->global->p2p, peer_addr,
@@ -6507,6 +6609,12 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
 				   wpa_s->p2p_auto_started.usec);
 		}
 		wpa_s->user_initiated_pd = 1;
+		if (password) {
+			wpa_s->pending_join_password_len = os_strlen(password);
+			os_memcpy(wpa_s->pending_join_password, password,
+				  os_strlen(password));
+			wpa_s->pending_join_password[wpa_s->pending_join_password_len] = '\0';
+		}
 		if (wpas_p2p_join(wpa_s, iface_addr, dev_addr, wps_method,
 				  auto_join, freq,
 				  group_ssid, group_ssid_len) < 0)
@@ -7341,7 +7449,7 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
 int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
 		       int freq, int vht_center_freq2, int ht40, int vht,
 		       int max_oper_chwidth, int he, int edmg,
-		       bool allow_6ghz)
+		       bool allow_6ghz, bool p2p2)
 {
 	struct p2p_go_neg_results params;
 	int selected_freq = 0;
@@ -7353,6 +7461,7 @@ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
 
 	os_free(wpa_s->global->add_psk);
 	wpa_s->global->add_psk = NULL;
+	wpa_s->p2p2 = p2p2;
 
 	/* Make sure we are not running find during connection establishment */
 	wpa_printf(MSG_DEBUG, "P2P: Stop any on-going P2P FIND");
@@ -8177,6 +8286,7 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
 	wpa_s->p2p_go_max_oper_chwidth = max_chwidth;
 	wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2;
 	wpa_s->p2p_go_edmg = !!edmg;
+	wpa_s->p2p2 = p2p2;
 	if (ssid->mode == WPAS_MODE_P2P_GO) {
 		role = P2P_INVITE_ROLE_GO;
 		if (peer_addr == NULL) {
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 61d4281..1e5f77a 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -45,7 +45,8 @@ int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s,
                                           int freq, struct wpa_ssid *ssid);
 int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
 		       int freq, int vht_center_freq2, int ht40, int vht,
-		       int max_oper_chwidth, int he, int edmg, bool allow_6ghz);
+		       int max_oper_chwidth, int he, int edmg, bool allow_6ghz,
+		       bool p2p2);
 int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
 				  struct wpa_ssid *ssid, int addr_allocated,
 				  int force_freq, int neg_freq,
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 8c596bb..4e87247 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1113,6 +1113,9 @@ struct wpa_supplicant {
 	u8 pending_join_dev_addr[ETH_ALEN];
 	u8 p2p_bootstrap_dev_addr[ETH_ALEN];
 	int pending_join_wps_method;
+	u16 pending_join_bootstrap;
+	char pending_join_password[100];
+	size_t pending_join_password_len;
 	u8 p2p_join_ssid[SSID_MAX_LEN];
 	size_t p2p_join_ssid_len;
 	int p2p_join_scan_count;
-- 
2.7.4




More information about the Hostap mailing list