diff mbox series

[v2,5/6] nl80211: add ack handler for extack cookies

Message ID 20200610083301.7496-6-markus.theil@tu-ilmenau.de
State Accepted
Headers show
Series nl80211: add support for control port tx status | expand

Commit Message

Markus Theil June 10, 2020, 8:33 a.m. UTC
This patch adds the actual extack cookie handler.

Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
---
 src/drivers/driver_nl80211.c | 45 +++++++++++++++++++++++++++++++++---
 1 file changed, 42 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 186fcd79a..123027482 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -278,6 +278,42 @@  static int ack_handler(struct nl_msg *msg, void *arg)
 	return NL_STOP;
 }
 
+
+struct nl80211_ack_ext_arg {
+	int *err;
+	void *ext_data;
+};
+
+
+static int ack_handler_cookie(struct nl_msg *msg, void *arg)
+{
+	struct nl80211_ack_ext_arg *ext_arg = arg;
+	struct nlattr *tb[NLMSGERR_ATTR_MAX + 1];
+	u64 *cookie = ext_arg->ext_data;
+	struct nlattr *attrs = NULL;
+	*ext_arg->err = 0;
+	int ack_len;
+	int attr_len;
+
+	ack_len = sizeof(struct nlmsghdr) + sizeof(int) + sizeof(struct nlmsghdr);
+	attrs = nlmsg_data(nlmsg_hdr(msg)) + sizeof(struct nlmsghdr) + sizeof(int);
+	attr_len = nlmsg_hdr(msg)->nlmsg_len - ack_len;
+
+	if (nlmsg_hdr(msg)->nlmsg_len <= ack_len)
+		goto out;
+
+	if(!(nlmsg_hdr(msg)->nlmsg_flags & NLM_F_ACK_TLVS))
+		goto out;
+
+	nla_parse(tb, NLMSGERR_ATTR_MAX, attrs, attr_len, NULL);
+	if (tb[NLMSGERR_ATTR_COOKIE])
+		*cookie = nla_get_u64(tb[NLMSGERR_ATTR_COOKIE]);
+
+out:
+	return NL_STOP;
+}
+
+
 static int finish_handler(struct nl_msg *msg, void *arg)
 {
 	int *ret = arg;
@@ -392,9 +428,12 @@  static int send_and_recv(struct nl80211_global *global,
 
 	nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
 	nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
-	if (ack_handler_custom)
-		nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler_custom, &err);
-	else
+	if (ack_handler_custom) {
+		struct nl80211_ack_ext_arg *ext_arg = ack_data;
+		ext_arg->err = &err;
+		nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM,
+			  ack_handler_custom, ack_data);
+	} else
 		nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
 
 	if (valid_handler)