diff mbox series

[v3,13/25] P2P: Cleanup of go-negotiation and invitation processing

Message ID 1722850403-8852-14-git-send-email-quic_shivbara@quicinc.com
State Deferred
Headers show
Series Add support for P2P2 | expand

Commit Message

Shivani Baranwal Aug. 5, 2024, 9:33 a.m. UTC
Add wrapper functions to process and prepare response for go negotiation
and invitation frames. Send the response action frames in handle_ functions.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
---
 src/p2p/p2p.c            |   9 ++-
 src/p2p/p2p_go_neg.c     | 152 ++++++++++++++++++++++++++++++++---------------
 src/p2p/p2p_i.h          |  45 +++++++++++---
 src/p2p/p2p_invitation.c |  61 +++++++++++--------
 4 files changed, 180 insertions(+), 87 deletions(-)
diff mbox series

Patch

diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index a66f0c4..d61f769 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -1927,17 +1927,16 @@  static void p2p_rx_p2p_action(struct p2p_data *p2p, const u8 *sa,
 
 	switch (data[0]) {
 	case P2P_GO_NEG_REQ:
-		p2p_process_go_neg_req(p2p, sa, data + 1, len - 1, rx_freq);
+		p2p_handle_go_neg_req(p2p, sa, data + 1, len - 1, rx_freq);
 		break;
 	case P2P_GO_NEG_RESP:
-		p2p_process_go_neg_resp(p2p, sa, data + 1, len - 1, rx_freq);
+		p2p_handle_go_neg_resp(p2p, sa, data + 1, len - 1, rx_freq);
 		break;
 	case P2P_GO_NEG_CONF:
-		p2p_process_go_neg_conf(p2p, sa, data + 1, len - 1);
+		p2p_handle_go_neg_conf(p2p, sa, data + 1, len - 1);
 		break;
 	case P2P_INVITATION_REQ:
-		p2p_process_invitation_req(p2p, sa, data + 1, len - 1,
-					   rx_freq);
+		p2p_handle_invitation_req(p2p, sa, data + 1, len - 1, rx_freq);
 		break;
 	case P2P_INVITATION_RESP:
 		p2p_process_invitation_resp(p2p, sa, data + 1, len - 1);
diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c
index 04e5139..0308216 100644
--- a/src/p2p/p2p_go_neg.c
+++ b/src/p2p/p2p_go_neg.c
@@ -801,21 +801,19 @@  void p2p_check_pref_chan(struct p2p_data *p2p, int go,
 }
 
 
-void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
-			    const u8 *data, size_t len, int rx_freq)
+int p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
+			   const u8 *data, size_t len, int rx_freq)
 {
 	struct p2p_device *dev = NULL;
-	struct wpabuf *resp;
 	struct p2p_message msg;
 	u8 status = P2P_SC_FAIL_INVALID_PARAMS;
 	int tie_breaker = 0;
-	int freq;
 
 	p2p_dbg(p2p, "Received GO Negotiation Request from " MACSTR "(freq=%d)",
 		MAC2STR(sa), rx_freq);
 
 	if (p2p_parse(data, len, &msg))
-		return;
+		return -1;
 
 	if (!msg.capability) {
 		p2p_dbg(p2p, "Mandatory Capability attribute missing from GO Negotiation Request");
@@ -890,7 +888,7 @@  void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
 			p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
 			p2p_go_neg_failed(p2p, *msg.status);
 			p2p_parse_free(&msg);
-			return;
+			return -1;
 		}
 		goto fail;
 	}
@@ -968,7 +966,7 @@  void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
 		    os_memcmp(sa, p2p->cfg->dev_addr, ETH_ALEN) > 0) {
 			p2p_dbg(p2p, "Do not reply since peer has higher address and GO Neg Request already sent");
 			p2p_parse_free(&msg);
-			return;
+			return -1;
 		}
 
 		if (dev->go_neg_req_sent &&
@@ -976,7 +974,7 @@  void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
 			p2p_dbg(p2p,
 				"Do not reply since peer is waiting for us to start a new GO Negotiation and GO Neg Request already sent");
 			p2p_parse_free(&msg);
-			return;
+			return -1;
 		}
 
 		go = p2p_go_det(p2p->go_intent, *msg.go_intent);
@@ -1086,7 +1084,10 @@  void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
 		p2p_set_state(p2p, P2P_GO_NEG);
 		p2p_clear_timeout(p2p);
 		dev->dialog_token = msg.dialog_token;
-		os_memcpy(dev->intended_addr, msg.intended_addr, ETH_ALEN);
+		if (!is_zero_ether_addr(msg.intended_addr)) {
+			p2p_dbg(p2p, "msg.intended_addr" MACSTR, MAC2STR(msg.intended_addr));
+			os_memcpy(dev->intended_addr, msg.intended_addr, ETH_ALEN);
+		}
 		p2p->go_neg_peer = dev;
 		eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, NULL);
 		status = P2P_SC_SUCCESS;
@@ -1095,22 +1096,13 @@  void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
 fail:
 	if (dev)
 		dev->status = status;
-	resp = p2p_build_go_neg_resp(p2p, dev, msg.dialog_token, status,
-				     !tie_breaker);
+	p2p->go_neg_resp = p2p_build_go_neg_resp(p2p, dev, msg.dialog_token,
+						 status, !tie_breaker);
+
 	p2p_parse_free(&msg);
-	if (resp == NULL)
-		return;
-	p2p_dbg(p2p, "Sending GO Negotiation Response");
-	if (rx_freq > 0)
-		freq = rx_freq;
-	else
-		freq = p2p_channel_to_freq(p2p->cfg->reg_class,
-					   p2p->cfg->channel);
-	if (freq < 0) {
-		p2p_dbg(p2p, "Unknown regulatory class/channel");
-		wpabuf_free(resp);
-		return;
-	}
+	if (!p2p->go_neg_resp)
+		return -1;
+
 	if (status == P2P_SC_SUCCESS) {
 		p2p->pending_action_state = P2P_PENDING_GO_NEG_RESPONSE;
 		dev->flags |= P2P_DEV_WAIT_GO_NEG_CONFIRM;
@@ -1128,13 +1120,38 @@  fail:
 	} else
 		p2p->pending_action_state =
 			P2P_PENDING_GO_NEG_RESPONSE_FAILURE;
-	if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
-			    p2p->cfg->dev_addr,
-			    wpabuf_head(resp), wpabuf_len(resp), 100) < 0) {
-		p2p_dbg(p2p, "Failed to send Action frame");
+	return 0;
+}
+
+void p2p_handle_go_neg_req(struct p2p_data *p2p, const u8 *sa, const u8 *data,
+			   size_t len, int rx_freq)
+{
+	int freq;
+
+	if (p2p_process_go_neg_req(p2p, sa, data, len, rx_freq))
+		return;
+
+	p2p_dbg(p2p, "Sending GO Negotiation Response");
+
+	if (rx_freq > 0)
+		freq = rx_freq;
+	else
+		freq = p2p_channel_to_freq(p2p->cfg->reg_class,
+					   p2p->cfg->channel);
+	if (freq < 0) {
+		p2p_dbg(p2p, "Unknown regulatory class/channel");
+		return;
 	}
 
-	wpabuf_free(resp);
+	if (p2p->go_neg_resp &&
+	    p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
+			    p2p->cfg->dev_addr, wpabuf_head(p2p->go_neg_resp),
+			    wpabuf_len(p2p->go_neg_resp), 100) < 0) {
+		p2p_dbg(p2p, "Failed to send Action frame");
+	}
+	wpabuf_free(p2p->go_neg_resp);
+	p2p->go_neg_resp = NULL;
+	return;
 }
 
 
@@ -1213,8 +1230,8 @@  static struct wpabuf * p2p_build_go_neg_conf(struct p2p_data *p2p,
 }
 
 
-void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
-			     const u8 *data, size_t len, int rx_freq)
+int p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa, const u8 *data,
+			    size_t len, int rx_freq)
 {
 	struct p2p_device *dev;
 	int go = -1;
@@ -1229,16 +1246,16 @@  void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
 	    dev != p2p->go_neg_peer) {
 		p2p_dbg(p2p, "Not ready for GO negotiation with " MACSTR,
 			MAC2STR(sa));
-		return;
+		return -1;
 	}
 
 	if (p2p_parse(data, len, &msg))
-		return;
+		return -1;
 
 	if (!(dev->flags & P2P_DEV_WAIT_GO_NEG_RESPONSE)) {
 		p2p_dbg(p2p, "Was not expecting GO Negotiation Response - ignore");
 		p2p_parse_free(&msg);
-		return;
+		return -1;
 	}
 	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
 	p2p_update_peer_6ghz_capab(dev, &msg);
@@ -1247,7 +1264,7 @@  void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
 		p2p_dbg(p2p, "Unexpected Dialog Token %u (expected %u)",
 			msg.dialog_token, dev->dialog_token);
 		p2p_parse_free(&msg);
-		return;
+		return -1;
 	}
 
 	if (!msg.status) {
@@ -1276,7 +1293,7 @@  void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
 		}
 		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
 		p2p_parse_free(&msg);
-		return;
+		return -1;
 	}
 
 	if (!msg.capability) {
@@ -1446,7 +1463,10 @@  void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
 	p2p_clear_timeout(p2p);
 
 	p2p_dbg(p2p, "GO Negotiation with " MACSTR, MAC2STR(sa));
-	os_memcpy(dev->intended_addr, msg.intended_addr, ETH_ALEN);
+	if (!is_zero_ether_addr(msg.intended_addr)) {
+		p2p_dbg(p2p, "msg.intended_addr" MACSTR, MAC2STR(msg.intended_addr));
+		os_memcpy(dev->intended_addr, msg.intended_addr, ETH_ALEN);
+	}
 
 fail:
 	/* Store GO Negotiation Confirmation to allow retransmission */
@@ -1454,15 +1474,18 @@  fail:
 	dev->go_neg_conf = p2p_build_go_neg_conf(p2p, dev, msg.dialog_token,
 						 status, msg.operating_channel,
 						 go);
-	p2p_parse_free(&msg);
 	if (dev->go_neg_conf == NULL)
-		return;
-	p2p_dbg(p2p, "Sending GO Negotiation Confirm");
+		return -1;
+
+	p2p->go_neg_conf = wpabuf_dup(dev->go_neg_conf);
+	p2p_parse_free(&msg);
+
 	if (status == P2P_SC_SUCCESS) {
 		p2p->pending_action_state = P2P_PENDING_GO_NEG_CONFIRM;
 		dev->go_state = go ? LOCAL_GO : REMOTE_GO;
 	} else
 		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
+
 	if (rx_freq > 0)
 		freq = rx_freq;
 	else
@@ -1471,7 +1494,39 @@  fail:
 	dev->go_neg_conf_freq = freq;
 	dev->go_neg_conf_sent = 0;
 
-	if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, sa,
+	if (status != P2P_SC_SUCCESS) {
+		p2p_dbg(p2p, "GO Negotiation failed");
+		dev->status = status;
+	}
+
+	return 0;
+}
+
+void p2p_handle_go_neg_resp(struct p2p_data *p2p, const u8 *sa, const u8 *data,
+			    size_t len, int rx_freq)
+{
+	int freq;
+	struct p2p_device *dev;
+
+	dev = p2p_get_device(p2p, sa);
+	if (dev == NULL || dev->wps_method == WPS_NOT_READY ||
+	    dev != p2p->go_neg_peer) {
+		p2p_dbg(p2p, "Not ready for GO negotiation with " MACSTR,
+			MAC2STR(sa));
+		return;
+	}
+
+	if (p2p_process_go_neg_resp(p2p, sa, data, len, rx_freq))
+		return;
+
+	p2p_dbg(p2p, "Sending GO Negotiation Confirm");
+	if (rx_freq > 0)
+		freq = rx_freq;
+	else
+		freq = dev->listen_freq;
+
+	if (dev->go_neg_conf &&
+	    p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, sa,
 			    wpabuf_head(dev->go_neg_conf),
 			    wpabuf_len(dev->go_neg_conf), 50) < 0) {
 		p2p_dbg(p2p, "Failed to send Action frame");
@@ -1479,15 +1534,18 @@  fail:
 		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
 	} else
 		dev->go_neg_conf_sent++;
-	if (status != P2P_SC_SUCCESS) {
-		p2p_dbg(p2p, "GO Negotiation failed");
-		p2p_go_neg_failed(p2p, status);
-	}
+
+	if (dev->status != P2P_SC_SUCCESS)
+		p2p_go_neg_failed(p2p, dev->status);
+
+	wpabuf_free(p2p->go_neg_conf);
+	p2p->go_neg_conf = NULL;
+	return;
 }
 
 
-void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa,
-			     const u8 *data, size_t len)
+void p2p_handle_go_neg_conf(struct p2p_data *p2p, const u8 *sa,
+			    const u8 *data, size_t len)
 {
 	struct p2p_device *dev;
 	struct p2p_message msg;
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index ef2bb9d..95bdd19 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -630,6 +630,25 @@  struct p2p_data {
 	bool allow_6ghz;
 
 	struct p2p_pairing_info *pairing_info;
+	/**
+	 * go_neg_resp - GO Negotiation Response frame
+	 */
+	struct wpabuf *go_neg_resp;
+
+	/**
+	 * go_neg_conf - GO Negotiation Confirmation frame
+	 */
+	struct wpabuf *go_neg_conf;
+
+	/**
+	 * invitation_req - Invitation request frame
+	 */
+	struct wpabuf *invitation_req;
+
+	/**
+	 * invitation_resp - Invitation Response frame
+	 */
+	struct wpabuf *invitation_resp;
 };
 
 /**
@@ -901,12 +920,16 @@  int p2p_start_sd(struct p2p_data *p2p, struct p2p_device *dev);
 int p2p_peer_channels_check(struct p2p_data *p2p, struct p2p_channels *own,
 			    struct p2p_device *dev,
 			    const u8 *channel_list, size_t channel_list_len);
-void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
-			    const u8 *data, size_t len, int rx_freq);
-void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
-			     const u8 *data, size_t len, int rx_freq);
-void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa,
-			     const u8 *data, size_t len);
+void p2p_handle_go_neg_req(struct p2p_data *p2p, const u8 *sa, const u8 *data,
+			   size_t len, int rx_freq);
+void p2p_handle_go_neg_resp(struct p2p_data *p2p, const u8 *sa, const u8 *data,
+			    size_t len, int rx_freq);
+void p2p_handle_go_neg_conf(struct p2p_data *p2p, const u8 *sa, const u8 *data,
+			    size_t len);
+int p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa, const u8 *data,
+			   size_t len, int rx_freq);
+int p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa, const u8 *data,
+			    size_t len, int rx_freq);
 int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev);
 u16 p2p_wps_method_pw_id(enum p2p_wps_method wps_method);
 void p2p_reselect_channel(struct p2p_data *p2p,
@@ -927,10 +950,14 @@  void p2p_process_pcea(struct p2p_data *p2p, struct p2p_message *msg,
 		      struct p2p_device *dev);
 
 /* p2p_invitation.c */
-void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
-				const u8 *data, size_t len, int rx_freq);
+void p2p_handle_invitation_req(struct p2p_data *p2p, const u8 *sa,
+			       const u8 *data, size_t len, int rx_freq);
+void p2p_handle_invitation_resp(struct p2p_data *p2p, const u8 *sa,
+				const u8 *data, size_t len);
+int p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
+			       const u8 *data, size_t len, int rx_freq);
 void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
-				 const u8 *data, size_t len);
+				const u8 *data, size_t len);
 int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev,
 		    const u8 *go_dev_addr, int dev_pw_id);
 void p2p_invitation_req_cb(struct p2p_data *p2p, int success);
diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c
index 70a7f6f..8ade838 100644
--- a/src/p2p/p2p_invitation.c
+++ b/src/p2p/p2p_invitation.c
@@ -181,14 +181,12 @@  static struct wpabuf * p2p_build_invitation_resp(struct p2p_data *p2p,
 }
 
 
-void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
-				const u8 *data, size_t len, int rx_freq)
+int p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
+			       const u8 *data, size_t len, int rx_freq)
 {
 	struct p2p_device *dev;
 	struct p2p_message msg;
-	struct wpabuf *resp = NULL;
 	u8 status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
-	int freq;
 	int go = 0;
 	u8 group_bssid[ETH_ALEN], *bssid;
 	int op_freq = 0;
@@ -202,7 +200,7 @@  void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
 		MAC2STR(sa), rx_freq);
 
 	if (p2p_parse(data, len, &msg))
-		return;
+		return -1;
 
 	dev = p2p_get_device(p2p, sa);
 	if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
@@ -385,21 +383,11 @@  fail:
 		bssid = group_bssid;
 	else
 		bssid = NULL;
-	resp = p2p_build_invitation_resp(p2p, dev, msg.dialog_token, status,
-					 bssid, reg_class, channel, channels);
-
-	if (resp == NULL)
-		goto out;
-
-	if (rx_freq > 0)
-		freq = rx_freq;
-	else
-		freq = p2p_channel_to_freq(p2p->cfg->reg_class,
-					   p2p->cfg->channel);
-	if (freq < 0) {
-		p2p_dbg(p2p, "Unknown regulatory class/channel");
-		goto out;
-	}
+	p2p->invitation_resp = p2p_build_invitation_resp(p2p, dev,
+							 msg.dialog_token,
+							 status, bssid,
+							 reg_class, channel,
+							 channels);
 
 	/*
 	 * Store copy of invitation data to be used when processing TX status
@@ -424,17 +412,38 @@  fail:
 	}
 	p2p->inv_status = status;
 	p2p->inv_op_freq = op_freq;
+	p2p_parse_free(&msg);
+	return 0;
+}
+
+
+void p2p_handle_invitation_req(struct p2p_data *p2p, const u8 *sa,
+			       const u8 *data, size_t len, int rx_freq)
+{
+	int freq;
+
+	if (p2p_process_invitation_req(p2p, sa, data, len, rx_freq))
+		return;
+
+	if (rx_freq > 0)
+		freq = rx_freq;
+	else
+		freq = p2p_channel_to_freq(p2p->cfg->reg_class,
+					   p2p->cfg->channel);
+	if (freq < 0)
+		p2p_dbg(p2p, "Unknown regulatory class/channel");
 
 	p2p->pending_action_state = P2P_PENDING_INVITATION_RESPONSE;
-	if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
+	if (p2p->invitation_resp &&
+	    p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
 			    p2p->cfg->dev_addr,
-			    wpabuf_head(resp), wpabuf_len(resp), 50) < 0) {
+			    wpabuf_head(p2p->invitation_resp),
+			    wpabuf_len(p2p->invitation_resp), 50) < 0)
 		p2p_dbg(p2p, "Failed to send Action frame");
-	}
 
-out:
-	wpabuf_free(resp);
-	p2p_parse_free(&msg);
+	wpabuf_free(p2p->invitation_resp);
+	p2p->invitation_resp = NULL;
+	return;
 }