]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Use ext ack handler for TX control port
authorMarkus Theil <markus.theil@tu-ilmenau.de>
Wed, 10 Jun 2020 08:32:59 +0000 (10:32 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 21 Jun 2020 14:55:28 +0000 (17:55 +0300)
Allow custom ack handler to be registered and use the ext ack handler
for TX control port to fetch the cookie information. If these cookies
are not supported by the current kernel, a value of 0 is returned.

Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
src/drivers/driver_nl80211.c

index d2b423c3025ee429bda04acd2c692f191f2a4b6b..da7038fea2b2639492e80a91e1661d64a10bbc7d 100644 (file)
@@ -278,6 +278,43 @@ 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;
+       size_t ack_len, attr_len;
+
+       *ext_arg->err = 0;
+       ack_len = sizeof(struct nlmsghdr) + sizeof(int) +
+               sizeof(struct nlmsghdr);
+       attrs = (struct nlattr *)
+               ((u8 *) nlmsg_data(nlmsg_hdr(msg)) + sizeof(struct nlmsghdr) +
+                sizeof(int));
+       if (nlmsg_hdr(msg)->nlmsg_len <= ack_len)
+               return NL_STOP;
+
+       attr_len = nlmsg_hdr(msg)->nlmsg_len - ack_len;
+
+       if(!(nlmsg_hdr(msg)->nlmsg_flags & NLM_F_ACK_TLVS))
+               return NL_STOP;
+
+       nla_parse(tb, NLMSGERR_ATTR_MAX, attrs, attr_len, NULL);
+       if (tb[NLMSGERR_ATTR_COOKIE])
+               *cookie = nla_get_u64(tb[NLMSGERR_ATTR_COOKIE]);
+
+       return NL_STOP;
+}
+
+
 static int finish_handler(struct nl_msg *msg, void *arg)
 {
        int *ret = arg;
@@ -392,7 +429,15 @@ 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);
-       nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
+       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)
                nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
@@ -5292,8 +5337,10 @@ static int nl80211_tx_control_port(void *priv, const u8 *dest,
                                   u16 proto, const u8 *buf, size_t len,
                                   int no_encrypt)
 {
+       struct nl80211_ack_ext_arg ext_arg;
        struct i802_bss *bss = priv;
        struct nl_msg *msg;
+       u64 cookie = 0;
        int ret;
 
        wpa_printf(MSG_DEBUG,
@@ -5312,11 +5359,18 @@ static int nl80211_tx_control_port(void *priv, const u8 *dest,
                return -ENOBUFS;
        }
 
-       ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
+       os_memset(&ext_arg, 0, sizeof(struct nl80211_ack_ext_arg));
+       ext_arg.ext_data = &cookie;
+       ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL,
+                                ack_handler_cookie, &ext_arg);
        if (ret)
                wpa_printf(MSG_DEBUG,
                           "nl80211: tx_control_port failed: ret=%d (%s)",
                           ret, strerror(-ret));
+       else
+               wpa_printf(MSG_DEBUG,
+                          "nl80211: tx_control_port cookie=0x%llx",
+                          (long long unsigned int) cookie);
 
        return ret;
 }