[PATCH v3 13/25] P2P: Cleanup of go-negotiation and invitation processing
Shivani Baranwal
quic_shivbara at quicinc.com
Mon Aug 5 02:33:11 PDT 2024
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 at 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 --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;
}
--
2.7.4
More information about the Hostap
mailing list