]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Add support to parse out link from error reply
authorBenjamin Berg <benjamin.berg@intel.com>
Mon, 20 Nov 2023 23:51:29 +0000 (01:51 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 25 Nov 2023 15:03:52 +0000 (17:03 +0200)
The kernel may report the link that caused an error by setting
NLMSGERR_ATTR_OFFS pointing to the NL80211_ATTR_MLO_LINKS element
that was the reason for the error.

Parse this information if the optional struct nl80211_err_info is
passed to send_and_recv_msgs().

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
src/drivers/driver_nl80211.c
src/drivers/driver_nl80211.h
src/drivers/driver_nl80211_capa.c
src/drivers/driver_nl80211_event.c
src/drivers/driver_nl80211_scan.c

index 38156c32ad07489020f773fe9b16f74012d990b4..2ff7b52bf5e9003f12c105eda2295dfdb4e14a5c 100644 (file)
@@ -341,17 +341,29 @@ static int finish_handler(struct nl_msg *msg, void *arg)
        return NL_SKIP;
 }
 
+struct nl80211_ack_err_args {
+       int err;
+       struct nl_msg *orig_msg;
+       struct nl80211_err_info *err_info;
+};
+
 static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
                         void *arg)
 {
+       struct nl80211_ack_err_args *err_args = arg;
        struct nlmsghdr *nlh = (struct nlmsghdr *) err - 1;
+       struct nlmsghdr *orig_nlh = nlmsg_hdr(err_args->orig_msg);
        int len = nlh->nlmsg_len;
        struct nlattr *attrs;
        struct nlattr *tb[NLMSGERR_ATTR_MAX + 1];
-       int *ret = arg;
        int ack_len = sizeof(*nlh) + sizeof(int) + sizeof(*nlh);
+       struct nlattr *mlo_links, *link_attr;
+       u32 offset;
+       int rem;
 
-       *ret = err->error;
+       err_args->err = err->error;
+       if (err_args->err_info)
+               err_args->err_info->link_id = -1;
 
        if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS))
                return NL_SKIP;
@@ -373,6 +385,41 @@ static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
                           len, (char *) nla_data(tb[NLMSGERR_ATTR_MSG]));
        }
 
+       if (!err_args->err_info)
+               return NL_SKIP;
+
+       /* Check if it was a per-link error report */
+
+       if (!tb[NLMSGERR_ATTR_OFFS] ||
+           os_memcmp(orig_nlh, &err->msg, sizeof(err->msg)) != 0)
+               return NL_SKIP;
+
+       offset = nla_get_u32(tb[NLMSGERR_ATTR_OFFS]);
+
+       mlo_links = nlmsg_find_attr(orig_nlh, GENL_HDRLEN,
+                                   NL80211_ATTR_MLO_LINKS);
+       if (!mlo_links)
+               return NL_SKIP;
+
+       nla_for_each_nested(link_attr, mlo_links, rem) {
+               struct nlattr *link_id;
+               size_t link_offset = (u8 *) link_attr - (u8 *) orig_nlh;
+
+               if (offset < link_offset ||
+                   offset >= link_offset + link_attr->nla_len)
+                       continue;
+
+               link_id = nla_find(nla_data(link_attr), nla_len(link_attr),
+                                  NL80211_ATTR_MLO_LINK_ID);
+               if (link_id) {
+                       err_args->err_info->link_id = nla_get_u8(link_id);
+                       wpa_printf(MSG_DEBUG,
+                                  "nl80211: kernel reports error for link: %d",
+                                  err_args->err_info->link_id);
+                       break;
+               }
+       }
+
        return NL_SKIP;
 }
 
@@ -445,14 +492,18 @@ static int send_and_recv(struct nl80211_global *global,
                         int (*valid_handler)(struct nl_msg *, void *),
                         void *valid_data,
                         int (*ack_handler_custom)(struct nl_msg *, void *),
-                        void *ack_data)
+                        void *ack_data,
+                        struct nl80211_err_info *err_info)
 {
        struct nl_cb *cb;
-       int err = -ENOMEM, opt;
+       struct nl80211_ack_err_args err;
+       int opt;
 
        if (!msg)
                return -ENOMEM;
 
+       err.err = -ENOMEM;
+
        cb = nl_cb_clone(global->nl_cb);
        if (!cb)
                goto out;
@@ -467,26 +518,28 @@ static int send_and_recv(struct nl80211_global *global,
        setsockopt(nl_socket_get_fd(nl_handle), SOL_NETLINK,
                   NETLINK_CAP_ACK, &opt, sizeof(opt));
 
-       err = nl_send_auto_complete(nl_handle, msg);
-       if (err < 0) {
+       err.err = nl_send_auto_complete(nl_handle, msg);
+       if (err.err < 0) {
                wpa_printf(MSG_INFO,
                           "nl80211: nl_send_auto_complete() failed: %s",
-                          nl_geterror(err));
+                          nl_geterror(err.err));
                /* Need to convert libnl error code to an errno value. For now,
                 * just hardcode this to EBADF; the real error reason is shown
                 * in that error print above. */
-               err = -EBADF;
+               err.err = -EBADF;
                goto out;
        }
 
-       err = 1;
+       err.err = 1;
+       err.orig_msg = msg;
+       err.err_info = err_info;
 
        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_FINISH, NL_CB_CUSTOM, finish_handler, &err.err);
        if (ack_handler_custom) {
                struct nl80211_ack_ext_arg *ext_arg = ack_data;
 
-               ext_arg->err = &err;
+               ext_arg->err = &err.err;
                nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM,
                          ack_handler_custom, ack_data);
        } else {
@@ -497,7 +550,7 @@ static int send_and_recv(struct nl80211_global *global,
                nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
                          valid_handler, valid_data);
 
-       while (err > 0) {
+       while (err.err > 0) {
                int res = nl_recvmsgs(nl_handle, cb);
 
                if (res == -NLE_DUMP_INTR) {
@@ -512,7 +565,7 @@ static int send_and_recv(struct nl80211_global *global,
                         * will stop and return an error. */
                        wpa_printf(MSG_DEBUG, "nl80211: %s; convert to -EAGAIN",
                                   nl_geterror(res));
-                       err = -EAGAIN;
+                       err.err = -EAGAIN;
                } else if (res < 0) {
                        wpa_printf(MSG_INFO,
                                   "nl80211: %s->nl_recvmsgs failed: %d (%s)",
@@ -524,7 +577,7 @@ static int send_and_recv(struct nl80211_global *global,
        /* Always clear the message as it can potentially contain keys */
        nl80211_nlmsg_clear(msg);
        nlmsg_free(msg);
-       return err;
+       return err.err;
 }
 
 
@@ -533,11 +586,12 @@ int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv,
                       int (*valid_handler)(struct nl_msg *, void *),
                       void *valid_data,
                       int (*ack_handler_custom)(struct nl_msg *, void *),
-                      void *ack_data)
+                      void *ack_data,
+                      struct nl80211_err_info *err_info)
 {
        return send_and_recv(drv->global, drv->global->nl, msg,
                             valid_handler, valid_data,
-                            ack_handler_custom, ack_data);
+                            ack_handler_custom, ack_data, err_info);
 }
 
 
@@ -554,7 +608,8 @@ static int send_and_recv_msgs_owner(struct wpa_driver_nl80211_data *drv,
                                    void *valid_data,
                                    int (*ack_handler_custom)(struct nl_msg *,
                                                              void *),
-                                   void *ack_data)
+                                   void *ack_data,
+                                   struct nl80211_err_info *err_info)
 {
        if (!msg)
                return -ENOMEM;
@@ -580,23 +635,24 @@ static int send_and_recv_msgs_owner(struct wpa_driver_nl80211_data *drv,
 
        return send_and_recv(drv->global, handle ? handle : drv->global->nl,
                             msg, valid_handler, valid_data,
-                            ack_handler_custom, ack_data);
+                            ack_handler_custom, ack_data, err_info);
 }
 
-
 static int
 send_and_recv_msgs_connect_handle(struct wpa_driver_nl80211_data *drv,
                                  struct nl_msg *msg, struct i802_bss *bss,
-                                 int set_owner)
+                                 int set_owner,
+                                 struct nl80211_err_info *err_info)
 {
        struct nl_sock *nl_connect = get_connect_handle(bss);
 
        if (nl_connect)
                return send_and_recv_msgs_owner(drv, msg, nl_connect, set_owner,
                                                process_bss_event, bss, NULL,
-                                               NULL);
+                                               NULL, err_info);
        else
-               return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+               return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL,
+                                         err_info);
 }
 
 
@@ -665,7 +721,7 @@ static int nl_get_multicast_id(struct nl80211_global *global,
        }
 
        ret = send_and_recv(global, global->nl, msg, family_handler, &res,
-                           NULL, NULL);
+                           NULL, NULL, NULL);
        if (ret == 0)
                ret = res.id;
        return ret;
@@ -794,7 +850,7 @@ int nl80211_get_wiphy_index(struct i802_bss *bss)
                return -1;
 
        if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data,
-                              NULL, NULL) == 0)
+                              NULL, NULL, NULL) == 0)
                return data.wiphy_idx;
        return -1;
 }
@@ -812,7 +868,7 @@ static enum nl80211_iftype nl80211_get_ifmode(struct i802_bss *bss)
                return NL80211_IFTYPE_UNSPECIFIED;
 
        if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data,
-                              NULL, NULL) == 0)
+                              NULL, NULL, NULL) == 0)
                return data.nlmode;
        return NL80211_IFTYPE_UNSPECIFIED;
 }
@@ -829,7 +885,7 @@ static int nl80211_get_macaddr(struct i802_bss *bss)
                return -1;
 
        return send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data,
-                                 NULL, NULL);
+                                 NULL, NULL, NULL);
 }
 
 
@@ -842,7 +898,7 @@ static int nl80211_get_4addr(struct i802_bss *bss)
 
        if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE)) ||
            send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data,
-                              NULL, NULL))
+                              NULL, NULL, NULL))
                return -1;
        return data.use_4addr;
 }
@@ -865,7 +921,7 @@ static int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv,
        }
 
        ret = send_and_recv(drv->global, w->nl_beacons, msg, NULL, NULL,
-                           NULL, NULL);
+                           NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: Register beacons command "
                           "failed: ret=%d (%s)",
@@ -1123,7 +1179,7 @@ static int nl80211_get_sta_mlo_info(void *priv,
 
                msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_INTERFACE);
                if (send_and_recv_msgs(drv, msg, get_mlo_info,
-                                      &drv->sta_mlo_info, NULL, NULL))
+                                      &drv->sta_mlo_info, NULL, NULL, NULL))
                        return -1;
        }
 
@@ -1666,7 +1722,7 @@ try_again:
        os_memset(&arg, 0, sizeof(arg));
        arg.drv = drv;
        ret = send_and_recv_msgs(drv, msg, nl80211_get_assoc_freq_handler,
-                                &arg, NULL, NULL);
+                                &arg, NULL, NULL, NULL);
        if (ret == -EAGAIN) {
                count++;
                if (count >= 10) {
@@ -1700,7 +1756,7 @@ try_again:
        os_memset(&arg, 0, sizeof(arg));
        arg.drv = drv;
        ret = send_and_recv_msgs(drv, msg, nl80211_get_assoc_freq_handler,
-                                &arg, NULL, NULL);
+                                &arg, NULL, NULL, NULL);
        if (ret == -EAGAIN) {
                count++;
                if (count >= 10) {
@@ -1789,7 +1845,7 @@ int nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv,
 
        msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
        return send_and_recv_msgs(drv, msg, get_link_noise, sig_change,
-                                 NULL, NULL);
+                                 NULL, NULL, NULL);
 }
 
 
@@ -1853,7 +1909,8 @@ static int nl80211_channel_info(void *priv, struct wpa_channel_info *ci)
        struct nl_msg *msg;
 
        msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_INTERFACE);
-       return send_and_recv_msgs(drv, msg, get_channel_info, ci, NULL, NULL);
+       return send_and_recv_msgs(drv, msg, get_channel_info, ci, NULL, NULL,
+                                 NULL);
 }
 
 
@@ -1902,7 +1959,7 @@ static int wpa_driver_nl80211_set_country(void *priv, const char *alpha2_arg)
                nlmsg_free(msg);
                return -EINVAL;
        }
-       if (send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL))
+       if (send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL))
                return -EINVAL;
        return 0;
 }
@@ -1949,7 +2006,7 @@ static int wpa_driver_nl80211_get_country(void *priv, char *alpha2)
 
        alpha2[0] = '\0';
        ret = send_and_recv_msgs(drv, msg, nl80211_get_country, alpha2,
-                                NULL, NULL);
+                                NULL, NULL, NULL);
        if (!alpha2[0])
                ret = -1;
 
@@ -2418,7 +2475,7 @@ static int nl80211_register_frame(struct i802_bss *bss,
        }
 
        ret = send_and_recv(drv->global, nl_handle, msg, NULL, NULL,
-                           NULL, NULL);
+                           NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: Register frame command "
                           "failed (type=%u): ret=%d (%s)",
@@ -2679,7 +2736,7 @@ static int nl80211_register_spurious_class3(struct i802_bss *bss)
 
        msg = nl80211_bss_msg(bss, 0, NL80211_CMD_UNEXPECTED_FRAME);
        ret = send_and_recv(bss->drv->global, bss->nl_mgmt, msg, NULL, NULL,
-                           NULL, NULL);
+                           NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: Register spurious class3 "
                           "failed: ret=%d (%s)",
@@ -2833,7 +2890,7 @@ static void nl80211_del_p2pdev(struct i802_bss *bss)
        int ret;
 
        msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_DEL_INTERFACE);
-       ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL, NULL);
 
        wpa_printf(MSG_DEBUG, "nl80211: Delete P2P Device %s (0x%llx): %s",
                   bss->ifname, (long long unsigned int) bss->wdev_id,
@@ -2848,7 +2905,7 @@ static int nl80211_set_p2pdev(struct i802_bss *bss, int start)
 
        msg = nl80211_cmd_msg(bss, 0, start ? NL80211_CMD_START_P2P_DEVICE :
                              NL80211_CMD_STOP_P2P_DEVICE);
-       ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL, NULL);
 
        wpa_printf(MSG_DEBUG, "nl80211: %s P2P Device %s (0x%llx): %s",
                   start ? "Start" : "Stop",
@@ -2920,7 +2977,7 @@ static void qca_vendor_test(struct wpa_driver_nl80211_data *drv)
        nla_nest_end(msg, params);
 
        ret = send_and_recv_msgs(drv, msg, qca_vendor_test_cmd_handler, drv,
-                                NULL, NULL);
+                                NULL, NULL, NULL);
        wpa_printf(MSG_DEBUG,
                   "nl80211: QCA vendor test command returned %d (%s)",
                   ret, strerror(-ret));
@@ -3067,7 +3124,7 @@ static int wpa_driver_nl80211_del_beacon(struct i802_bss *bss,
                }
        }
 
-       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
 }
 
 
@@ -3345,7 +3402,7 @@ static int issue_key_mgmt_set_key(struct wpa_driver_nl80211_data *drv,
                nlmsg_free(msg);
                return -1;
        }
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG,
                           "nl80211: Key management set key failed: ret=%d (%s)",
@@ -3385,7 +3442,7 @@ static int nl80211_set_pmk(struct wpa_driver_nl80211_data *drv,
                return -ENOBUFS;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: Set PMK failed: ret=%d (%s)",
                           ret, strerror(-ret));
@@ -3559,7 +3616,7 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss,
                        goto fail;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE)
                ret = 0;
        if (ret)
@@ -3628,7 +3685,7 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss,
                        goto fail;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret)
                wpa_printf(MSG_DEBUG,
                           "nl80211: set_key default failed; err=%d %s",
@@ -3754,9 +3811,10 @@ int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
 
        if (nl_connect)
                ret = send_and_recv(drv->global, nl_connect, msg,
-                                   process_bss_event, bss, NULL, NULL);
+                                   process_bss_event, bss, NULL, NULL, NULL);
        else
-               ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+               ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL,
+                                        NULL);
        if (ret) {
                wpa_dbg(drv->ctx, MSG_DEBUG,
                        "nl80211: MLME command failed: reason=%u ret=%d (%s)",
@@ -4034,7 +4092,7 @@ retry:
                        goto fail;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        msg = NULL;
        if (ret) {
                wpa_dbg(drv->ctx, MSG_DEBUG,
@@ -4395,7 +4453,7 @@ static int nl80211_set_bss(struct i802_bss *bss, int cts, int preamble,
                return -ENOBUFS;
        }
 
-       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
 }
 
 
@@ -4454,7 +4512,7 @@ static int wpa_driver_nl80211_set_acl(void *priv,
        }
        nlmsg_free(acl);
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: Failed to set MAC ACL: %d (%s)",
                           ret, strerror(-ret));
@@ -4506,7 +4564,7 @@ static int nl80211_set_mesh_config(void *priv,
                return ret;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_ERROR,
                           "nl80211: Mesh config set failed: %d (%s)",
@@ -4652,7 +4710,7 @@ static int nl80211_set_multicast_to_unicast(struct i802_bss *bss,
                return -ENOBUFS;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
 
        switch (ret) {
        case 0:
@@ -4877,7 +4935,7 @@ static void qca_set_allowed_ap_freqs(struct wpa_driver_nl80211_data *drv,
        nla_nest_end(msg, freqs_list);
        nla_nest_end(msg, params);
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret)
                wpa_printf(MSG_ERROR,
                           "nl80211: Failed set AP alllowed frequency list: %d (%s)",
@@ -5370,7 +5428,7 @@ static int wpa_driver_nl80211_set_ap(void *priv,
                                         int_array_len(params->allowed_freqs));
 #endif /* CONFIG_DRIVER_NL80211_QCA */
 
-       ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 1);
+       ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 1, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
                           ret, strerror(-ret));
@@ -5476,7 +5534,7 @@ static int nl80211_set_channel(struct i802_bss *bss,
                }
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret == 0) {
                nl80211_link_set_freq(bss, freq->link_id, freq->freq);
                return 0;
@@ -5817,7 +5875,7 @@ static int wpa_driver_nl80211_sta_add(void *priv,
                        goto fail;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        msg = NULL;
        if (ret)
                wpa_printf(MSG_DEBUG, "nl80211: %s result: %d (%s)",
@@ -5888,7 +5946,7 @@ static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr,
                return -ENOBUFS;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        wpa_printf(MSG_DEBUG, "nl80211: sta_remove -> DEL_STATION %s " MACSTR
                   " --> %d (%s)",
                   bss->ifname, MAC2STR(addr), ret, strerror(-ret));
@@ -5919,7 +5977,7 @@ void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, int ifidx)
        }
 
        msg = nl80211_ifindex_msg(drv, ifidx, 0, NL80211_CMD_DEL_INTERFACE);
-       if (send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL) == 0)
+       if (send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL) == 0)
                return;
        wpa_printf(MSG_ERROR, "Failed to remove interface (ifidx=%d)", ifidx);
 }
@@ -6003,7 +6061,7 @@ static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
            nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
                goto fail;
 
-       ret = send_and_recv_msgs(drv, msg, handler, arg, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, handler, arg, NULL, NULL, NULL);
        msg = NULL;
        if (ret) {
        fail:
@@ -6185,7 +6243,7 @@ static int nl80211_tx_control_port(void *priv, const u8 *dest,
        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);
+                                ack_handler_cookie, &ext_arg, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG,
                           "nl80211: tx_control_port failed: ret=%d (%s)",
@@ -6352,7 +6410,7 @@ static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr,
        if (nla_put(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd))
                goto fail;
 
-       return send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
+       return send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL, NULL);
 fail:
        nlmsg_free(msg);
        return -ENOBUFS;
@@ -6375,7 +6433,7 @@ static int driver_nl80211_sta_set_airtime_weight(void *priv, const u8 *addr,
            nla_put_u16(msg, NL80211_ATTR_AIRTIME_WEIGHT, weight))
                goto fail;
 
-       ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG,
                           "nl80211: SET_STATION[AIRTIME_WEIGHT] failed: ret=%d (%s)",
@@ -6425,7 +6483,8 @@ static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv,
        int ret;
 
        msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_IBSS);
-       ret = send_and_recv_msgs_connect_handle(drv, msg, drv->first_bss, 1);
+       ret = send_and_recv_msgs_connect_handle(drv, msg, drv->first_bss, 1,
+                                               NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d "
                           "(%s)", ret, strerror(-ret));
@@ -6572,7 +6631,8 @@ retry:
        if (ret < 0)
                goto fail;
 
-       ret = send_and_recv_msgs_connect_handle(drv, msg, drv->first_bss, 1);
+       ret = send_and_recv_msgs_connect_handle(drv, msg, drv->first_bss, 1,
+                                               NULL);
        msg = NULL;
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)",
@@ -7142,7 +7202,7 @@ skip_auth_type:
        if (ret)
                goto fail;
 
-       ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 1);
+       ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 1, NULL);
        msg = NULL;
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
@@ -7258,7 +7318,8 @@ static int wpa_driver_nl80211_associate(
                        goto fail;
        }
 
-       ret = send_and_recv_msgs_connect_handle(drv, msg, drv->first_bss, 1);
+       ret = send_and_recv_msgs_connect_handle(drv, msg, drv->first_bss, 1,
+                                               NULL);
        msg = NULL;
        if (ret) {
                wpa_dbg(drv->ctx, MSG_DEBUG,
@@ -7289,7 +7350,7 @@ static int nl80211_set_mode(struct wpa_driver_nl80211_data *drv,
        if (!msg || nla_put_u32(msg, NL80211_ATTR_IFTYPE, mode))
                goto fail;
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        msg = NULL;
        if (!ret)
                return 0;
@@ -7553,7 +7614,7 @@ static int wpa_driver_nl80211_set_supp_port(void *priv, int authorized)
                return -ENOBUFS;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (!ret)
                return 0;
        wpa_printf(MSG_DEBUG, "nl80211: Failed to set STA flag: %d (%s)",
@@ -7620,7 +7681,8 @@ static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
        }
 
        os_memset(seq, 0, 6);
-       res = send_and_recv_msgs(drv, msg, get_key_handler, seq, NULL, NULL);
+       res = send_and_recv_msgs(drv, msg, get_key_handler, seq, NULL, NULL,
+                                NULL);
        if (res) {
                wpa_printf(MSG_DEBUG,
                           "nl80211: Failed to get current TX sequence for a key (link_id=%d idx=%d): %d (%s)",
@@ -7650,7 +7712,7 @@ static int i802_set_rts(void *priv, int rts)
                return -ENOBUFS;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (!ret)
                return 0;
        wpa_printf(MSG_DEBUG, "nl80211: Failed to set RTS threshold %d: "
@@ -7678,7 +7740,7 @@ static int i802_set_frag(void *priv, int frag)
                return -ENOBUFS;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (!ret)
                return 0;
        wpa_printf(MSG_DEBUG, "nl80211: Failed to set fragmentation threshold "
@@ -7700,7 +7762,7 @@ static int i802_flush(void *priv)
         * XXX: FIX! this needs to flush all VLANs too
         */
        msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_STATION);
-       res = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
+       res = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (res) {
                wpa_printf(MSG_DEBUG, "nl80211: Station flush failed: ret=%d "
                           "(%s)", res, strerror(-res));
@@ -8031,7 +8093,8 @@ int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv,
                return -ENOBUFS;
        }
 
-       return send_and_recv_msgs(drv, msg, get_sta_handler, data, NULL, NULL);
+       return send_and_recv_msgs(drv, msg, get_sta_handler, data, NULL, NULL,
+                                 NULL);
 }
 
 
@@ -8048,7 +8111,7 @@ static int i802_read_sta_data(struct i802_bss *bss,
        }
 
        return send_and_recv_msgs(bss->drv, msg, get_sta_handler, data,
-                                 NULL, NULL);
+                                 NULL, NULL, NULL);
 }
 
 
@@ -8110,7 +8173,7 @@ static int i802_set_tx_queue_params(void *priv, int queue, int aifs,
            nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
                goto fail;
 
-       res = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       res = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        wpa_printf(MSG_DEBUG,
                   "nl80211: TX queue param set: queue=%d aifs=%d cw_min=%d cw_max=%d burst_time=%d --> res=%d",
                   queue, aifs, cw_min, cw_max, burst_time, res);
@@ -8145,7 +8208,7 @@ static int i802_set_sta_vlan(struct i802_bss *bss, const u8 *addr,
                return -ENOBUFS;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret < 0) {
                wpa_printf(MSG_ERROR, "nl80211: NL80211_ATTR_STA_VLAN (addr="
                           MACSTR " ifname=%s vlan_id=%d) failed: %d (%s)",
@@ -9005,7 +9068,8 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss,
                goto fail;
 
        cookie = 0;
-       ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie, NULL, NULL,
+                                NULL);
        msg = NULL;
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: Frame command failed: ret=%d "
@@ -9139,7 +9203,7 @@ static void nl80211_frame_wait_cancel(struct i802_bss *bss, u64 cookie)
                return;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret)
                wpa_printf(MSG_DEBUG, "nl80211: wait cancel failed: ret=%d "
                           "(%s)", ret, strerror(-ret));
@@ -9188,7 +9252,8 @@ static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq,
        }
 
        cookie = 0;
-       ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie, NULL, NULL,
+                                NULL);
        if (ret == 0) {
                wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel cookie "
                           "0x%llx for freq=%u MHz duration=%u",
@@ -9228,7 +9293,7 @@ static int wpa_driver_nl80211_cancel_remain_on_channel(void *priv)
                return -1;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret == 0)
                return 0;
        wpa_printf(MSG_DEBUG, "nl80211: Failed to cancel remain-on-channel: "
@@ -9325,7 +9390,7 @@ static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
 
        nla_nest_end(msg, bands);
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: Set TX rates failed: ret=%d "
                           "(%s)", ret, strerror(-ret));
@@ -9382,7 +9447,7 @@ static void nl80211_remove_links(struct i802_bss *bss)
                        return;
                }
 
-               ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+               ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
                if (ret) {
                        wpa_printf(MSG_ERROR,
                                   "nl80211: remove link (%d) failed. ret=%d (%s)",
@@ -9481,7 +9546,7 @@ static int nl80211_signal_monitor(void *priv, int threshold, int hysteresis)
        }
        nla_nest_end(msg, cqm);
 
-       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
 }
 
 
@@ -9519,7 +9584,8 @@ static int nl80211_get_channel_width(struct wpa_driver_nl80211_data *drv,
        struct nl_msg *msg;
 
        msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_INTERFACE);
-       return send_and_recv_msgs(drv, msg, get_channel_width, sig, NULL, NULL);
+       return send_and_recv_msgs(drv, msg, get_channel_width, sig, NULL, NULL,
+                                 NULL);
 }
 
 
@@ -9604,7 +9670,7 @@ static int nl80211_get_links_noise(struct wpa_driver_nl80211_data *drv,
 
        msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
        return send_and_recv_msgs(drv, msg, get_links_noise, mlo_sig,
-                                 NULL, NULL);
+                                 NULL, NULL, NULL);
 }
 
 
@@ -9659,7 +9725,7 @@ static int nl80211_get_links_channel_width(struct wpa_driver_nl80211_data *drv,
 
        msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_INTERFACE);
        return send_and_recv_msgs(drv, msg, get_links_channel_width, mlo_sig,
-                                 NULL, NULL);
+                                 NULL, NULL, NULL);
 }
 
 
@@ -9890,7 +9956,7 @@ static int nl80211_pmkid(struct i802_bss *bss, int cmd,
                return -ENOBUFS;
        }
 
-       return send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
+       return send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL, NULL);
 }
 
 
@@ -9966,7 +10032,7 @@ static int nl80211_flush_pmkid(void *priv)
        msg = nl80211_bss_msg(bss, 0, NL80211_CMD_FLUSH_PMKSA);
        if (!msg)
                return -ENOBUFS;
-       return send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
+       return send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL, NULL);
 }
 
 
@@ -10131,7 +10197,7 @@ static int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq)
        do {
                wpa_printf(MSG_DEBUG, "nl80211: Fetch survey data");
                err = send_and_recv_msgs(drv, msg, survey_handler,
-                                        survey_results, NULL, NULL);
+                                        survey_results, NULL, NULL, NULL);
        } while (err > 0);
 
        if (err)
@@ -10171,7 +10237,7 @@ static void nl80211_set_rekey_info(void *priv, const u8 *kek, size_t kek_len,
 
        nla_nest_end(msg, replay_nested);
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret == -EOPNOTSUPP) {
                wpa_printf(MSG_DEBUG,
                           "nl80211: Driver does not support rekey offload");
@@ -10238,7 +10304,8 @@ static void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr,
                return;
        }
 
-       ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie, NULL, NULL,
+                                NULL);
        if (ret < 0) {
                wpa_printf(MSG_DEBUG, "nl80211: Client probe request for "
                           MACSTR " failed: ret=%d (%s)",
@@ -10264,7 +10331,7 @@ static int nl80211_set_power_save(struct i802_bss *bss, int enabled)
                return -ENOBUFS;
        }
 
-       ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret < 0) {
                wpa_printf(MSG_DEBUG,
                           "nl80211: Setting PS state %s failed: %d (%s)",
@@ -10324,7 +10391,7 @@ static int nl80211_start_radar_detection(void *priv,
                return -1;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret == 0)
                return 0;
        wpa_printf(MSG_DEBUG, "nl80211: Failed to start radar detection: "
@@ -10383,7 +10450,7 @@ nl80211_tdls_set_discovery_resp_link(struct wpa_driver_nl80211_data *drv,
        }
        nla_nest_end(msg, params);
 
-       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
 #else /* CONFIG_DRIVER_NL80211_QCA */
        wpa_printf(MSG_ERROR,
                   "nl80211: Setting TX link for TDLS Discovery Response not supported");
@@ -10421,7 +10488,7 @@ static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,
            nla_put(msg, NL80211_ATTR_IE, len, buf))
                goto fail;
 
-       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
 
 fail:
        nlmsg_free(msg);
@@ -10471,7 +10538,7 @@ static int nl80211_tdls_oper(void *priv, enum tdls_oper oper, const u8 *peer)
                return -ENOBUFS;
        }
 
-       res = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       res = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        wpa_printf(MSG_DEBUG, "nl80211: TDLS_OPER: oper=%d mac=" MACSTR
                   " --> res=%d (%s)", nl80211_oper, MAC2STR(peer), res,
                   strerror(-res));
@@ -10505,7 +10572,7 @@ nl80211_tdls_enable_channel_switch(void *priv, const u8 *addr, u8 oper_class,
                return ret;
        }
 
-       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
 }
 
 
@@ -10531,7 +10598,7 @@ nl80211_tdls_disable_channel_switch(void *priv, const u8 *addr)
                return -ENOBUFS;
        }
 
-       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
 }
 
 #endif /* CONFIG TDLS */
@@ -10676,7 +10743,7 @@ static int wpa_driver_nl80211_update_ft_ies(void *priv, const u8 *md,
                return -ENOBUFS;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: update_ft_ies failed "
                           "err=%d (%s)", ret, strerror(-ret));
@@ -10704,7 +10771,7 @@ static int nl80211_update_dh_ie(void *priv, const u8 *peer_mac,
                return -ENOBUFS;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG,
                           "nl80211: update_dh_ie failed err=%d (%s)",
@@ -10957,7 +11024,7 @@ static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen)
            nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG) &&
            nla_put_u32(msg, NL80211_ATTR_WIPHY, drv->wiphy_idx) == 0) {
                if (send_and_recv_msgs(drv, msg, nl80211_get_country,
-                                      alpha2, NULL, NULL) == 0 &&
+                                      alpha2, NULL, NULL, NULL) == 0 &&
                    alpha2[0]) {
                        res = os_snprintf(pos, end - pos, "country=%s\n",
                                          alpha2);
@@ -11119,7 +11186,7 @@ static int nl80211_switch_channel(void *priv, struct csa_settings *settings)
                goto fail;
 
        nla_nest_end(msg, beacon_csa);
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: switch_channel failed err=%d (%s)",
                           ret, strerror(-ret));
@@ -11200,7 +11267,7 @@ static int nl80211_switch_color(void *priv, struct cca_settings *settings)
        }
 
        nla_nest_end(msg, beacon_cca);
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG,
                           "nl80211: switch_color failed err=%d (%s)",
@@ -11241,7 +11308,7 @@ static int nl80211_add_ts(void *priv, u8 tsid, const u8 *addr,
                return -ENOBUFS;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret)
                wpa_printf(MSG_DEBUG, "nl80211: add_ts failed err=%d (%s)",
                           ret, strerror(-ret));
@@ -11268,7 +11335,7 @@ static int nl80211_del_ts(void *priv, u8 tsid, const u8 *addr)
                return -ENOBUFS;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret)
                wpa_printf(MSG_DEBUG, "nl80211: del_ts failed err=%d (%s)",
                           ret, strerror(-ret));
@@ -11375,7 +11442,7 @@ static int nl80211_vendor_cmd(void *priv, unsigned int vendor_id,
                ret = send_and_recv_msgs_owner(drv, msg,
                                               get_connect_handle(bss), 0,
                                               cmd_reply_handler, buf,
-                                              NULL, NULL);
+                                              NULL, NULL, NULL);
                if (ret)
                        wpa_printf(MSG_DEBUG, "nl80211: command failed err=%d",
                                   ret);
@@ -11400,7 +11467,7 @@ static int nl80211_vendor_cmd(void *priv, unsigned int vendor_id,
                goto fail;
 
        ret = send_and_recv_msgs(drv, msg, vendor_reply_handler, buf,
-                                NULL, NULL);
+                                NULL, NULL, NULL);
        if (ret)
                wpa_printf(MSG_DEBUG, "nl80211: vendor command failed err=%d",
                           ret);
@@ -11429,7 +11496,7 @@ static int nl80211_set_qos_map(void *priv, const u8 *qos_map_set,
                return -ENOBUFS;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret)
                wpa_printf(MSG_DEBUG, "nl80211: Setting QoS Map failed");
 
@@ -11465,7 +11532,7 @@ static int nl80211_get_wowlan(void *priv)
        msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_WOWLAN);
 
        ret = send_and_recv_msgs(drv, msg, get_wowlan_handler, &wowlan_enabled,
-                                NULL, NULL);
+                                NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: Getting wowlan status failed");
                return 0;
@@ -11512,7 +11579,7 @@ static int nl80211_set_wowlan(void *priv,
 
        nla_nest_end(msg, wowlan_triggers);
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret)
                wpa_printf(MSG_DEBUG, "nl80211: Setting wowlan failed");
 
@@ -11551,7 +11618,7 @@ static int nl80211_roaming(void *priv, int allowed, const u8 *bssid)
        }
        nla_nest_end(msg, params);
 
-       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
 }
 
 
@@ -11579,7 +11646,7 @@ static int nl80211_disable_fils(void *priv, int disable)
        }
        nla_nest_end(msg, params);
 
-       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
 }
 
 
@@ -11636,7 +11703,7 @@ static int nl80211_set_bssid_tmp_disallow(void *priv, unsigned int num_bssid,
        nla_nest_end(msg, nlbssids);
        nla_nest_end(msg, params);
 
-       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
 
 fail:
        nlmsg_free(msg);
@@ -11674,7 +11741,7 @@ static int nl80211_add_sta_node(void *priv, const u8 *addr, u16 auth_alg)
        }
        nla_nest_end(msg, params);
 
-       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
 }
 
 #endif /* CONFIG_DRIVER_NL80211_QCA */
@@ -11859,7 +11926,7 @@ static int nl80211_join_mesh(struct i802_bss *bss,
        if (nl80211_put_mesh_config(msg, &params->conf) < 0)
                goto fail;
 
-       ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 1);
+       ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 1, NULL);
        msg = NULL;
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: mesh join failed: ret=%d (%s)",
@@ -11916,7 +11983,7 @@ static int wpa_driver_nl80211_leave_mesh(void *priv)
 
        wpa_printf(MSG_DEBUG, "nl80211: mesh leave (ifindex=%d)", drv->ifindex);
        msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_MESH);
-       ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 0);
+       ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 0, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: mesh leave failed: ret=%d (%s)",
                           ret, strerror(-ret));
@@ -11952,7 +12019,7 @@ static int nl80211_probe_mesh_link(void *priv, const u8 *addr, const u8 *eth,
                return -ENOBUFS;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: mesh link probe to " MACSTR
                           " failed: ret=%d (%s)",
@@ -12369,7 +12436,7 @@ static int nl80211_qca_do_acs(struct wpa_driver_nl80211_data *drv,
                   params->vht_enabled, params->eht_enabled, params->ch_width,
                   params->edmg_enabled);
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG,
                           "nl80211: Failed to invoke driver ACS function: %s",
@@ -12427,7 +12494,7 @@ static int nl80211_set_band(void *priv, u32 band_mask)
        }
        nla_nest_end(msg, data);
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG,
                           "nl80211: Driver setband function failed: %s",
@@ -12630,7 +12697,7 @@ static int nl80211_get_pref_freq_list(void *priv,
        if (freq_list)
                os_memset(freq_list, 0, *num * sizeof(struct weighted_pcl));
        ret = send_and_recv_msgs(drv, msg, preferred_freq_info_handler, &param,
-                                NULL, NULL);
+                                NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_ERROR,
                           "%s: err in send_and_recv_msgs", __func__);
@@ -12684,7 +12751,7 @@ static int nl80211_set_prob_oper_freq(void *priv, unsigned int freq)
        }
        nla_nest_end(msg, params);
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        msg = NULL;
        if (ret) {
                wpa_printf(MSG_ERROR, "%s: err in send_and_recv_msgs",
@@ -12740,7 +12807,7 @@ static int nl80211_p2p_lo_start(void *priv, unsigned int freq,
                goto fail;
 
        nla_nest_end(msg, container);
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        msg = NULL;
        if (ret) {
                wpa_printf(MSG_DEBUG,
@@ -12775,7 +12842,7 @@ static int nl80211_p2p_lo_stop(void *priv)
                return -1;
        }
 
-       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
 }
 
 
@@ -12814,7 +12881,7 @@ static int nl80211_set_tdls_mode(void *priv, int tdls_external_control)
 
        nla_nest_end(msg, params);
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        msg = NULL;
        if (ret) {
                wpa_printf(MSG_ERROR,
@@ -13007,7 +13074,7 @@ nl80211_get_bss_transition_status(void *priv, struct wpa_bss_trans_info *params)
 
        ret = send_and_recv_msgs(drv, msg,
                                 nl80211_get_bss_transition_status_handler,
-                                info, NULL, NULL);
+                                info, NULL, NULL, NULL);
        msg = NULL;
        if (ret) {
                wpa_printf(MSG_ERROR,
@@ -13060,7 +13127,7 @@ static int nl80211_ignore_assoc_disallow(void *priv, int ignore_disallow)
 
        nla_nest_end(msg, attr);
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        msg = NULL;
        if (ret) {
                wpa_printf(MSG_ERROR,
@@ -13131,7 +13198,7 @@ static int nl80211_send_pasn_resp(void *priv, struct pasn_auth *params)
        nla_nest_end(msg, nlpeers);
        nla_nest_end(msg, attr);
 
-       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
 
 fail:
        nlmsg_free(msg);
@@ -13227,7 +13294,7 @@ static int nl80211_set_secure_ranging_ctx(void *priv,
        }
        nla_nest_end(msg, attr);
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret)
                wpa_printf(MSG_DEBUG,
                           "nl80211: Set secure ranging context failed: ret=%d (%s)",
@@ -13281,7 +13348,7 @@ static int wpa_driver_do_broadcom_acs(struct wpa_driver_nl80211_data *drv,
                   params->hw_mode, params->ht_enabled, params->ht40_enabled,
                   params->vht_enabled, params->ch_width);
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_ERROR,
                           "nl80211: BRCM Failed to invoke driver ACS function: %s",
@@ -13536,7 +13603,7 @@ static int nl80211_update_connection_params(
            nl80211_put_fils_connect_params(drv, params, msg))
                goto fail;
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        msg = NULL;
        if (ret)
                wpa_dbg(drv->ctx, MSG_DEBUG,
@@ -13579,7 +13646,7 @@ static int nl80211_send_external_auth_status(void *priv,
            (params->bssid &&
             nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid)))
                goto fail;
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        msg = NULL;
        if (ret) {
                wpa_printf(MSG_DEBUG,
@@ -13619,7 +13686,7 @@ static int nl80211_set_4addr_mode(void *priv, const char *bridge_ifname,
                bss->added_if_into_bridge = 0;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        msg = NULL;
        if (ret && val && nl80211_get_4addr(bss) == 1) {
                wpa_printf(MSG_DEBUG,
@@ -13717,7 +13784,7 @@ static int nl80211_link_add(void *priv, u8 link_id, const u8 *addr)
                return -ENOBUFS;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: add link failed. ret=%d (%s)",
                           ret, strerror(-ret));
index d4197399369de1ef6d7f601df52b50855d33fba9..f82f604e9017b40e1a4791dd1ddbf523a2f92af3 100644 (file)
@@ -269,6 +269,10 @@ struct wpa_driver_nl80211_data {
 
 struct nl_msg;
 
+struct nl80211_err_info {
+       int link_id;
+};
+
 void * nl80211_cmd(struct wpa_driver_nl80211_data *drv,
                   struct nl_msg *msg, int flags, uint8_t cmd);
 struct nl_msg * nl80211_cmd_msg(struct i802_bss *bss, int flags, uint8_t cmd);
@@ -279,7 +283,8 @@ int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, struct nl_msg *msg,
                       int (*valid_handler)(struct nl_msg *, void *),
                       void *valid_data,
                       int (*ack_handler_custom)(struct nl_msg *, void *),
-                      void *ack_data);
+                      void *ack_data,
+                      struct nl80211_err_info *err_info);
 struct nl_sock * get_connect_handle(struct i802_bss *bss);
 int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
                         const char *ifname, enum nl80211_iftype iftype,
index 544e54dbc70d366e35d2c3ef46529eaa4a5f769f..8e033ceb0ed1652110776c8d73784384dd9b17fa 100644 (file)
@@ -51,7 +51,7 @@ static u32 get_nl80211_protocol_features(struct wpa_driver_nl80211_data *drv)
        }
 
        if (send_and_recv_msgs(drv, msg, protocol_feature_handler, &feat,
-                              NULL, NULL) == 0)
+                              NULL, NULL, NULL) == 0)
                return feat;
 
        return 0;
@@ -1202,7 +1202,8 @@ static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data *drv,
                return -1;
        }
 
-       if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info, NULL, NULL))
+       if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info, NULL, NULL,
+                              NULL))
                return -1;
 
        if (info->auth_supported)
@@ -1312,7 +1313,7 @@ static void qca_nl80211_check_dfs_capa(struct wpa_driver_nl80211_data *drv)
        }
 
        ret = send_and_recv_msgs(drv, msg, dfs_info_handler, &dfs_capability,
-                                NULL, NULL);
+                                NULL, NULL, NULL);
        if (!ret && dfs_capability)
                drv->capa.flags |= WPA_DRIVER_FLAGS_DFS_OFFLOAD;
 }
@@ -1400,7 +1401,7 @@ static void qca_nl80211_get_features(struct wpa_driver_nl80211_data *drv)
        os_memset(&info, 0, sizeof(info));
        info.capa = &drv->capa;
        ret = send_and_recv_msgs(drv, msg, features_info_handler, &info,
-                                NULL, NULL);
+                                NULL, NULL, NULL);
        if (ret || !info.flags)
                return;
 
@@ -2541,7 +2542,7 @@ static int nl80211_set_regulatory_flags(struct wpa_driver_nl80211_data *drv,
        }
 
        return send_and_recv_msgs(drv, msg, nl80211_get_reg, results,
-                                 NULL, NULL);
+                                 NULL, NULL, NULL);
 }
 
 
@@ -2634,7 +2635,7 @@ nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags,
        }
 
        if (send_and_recv_msgs(drv, msg, phy_info_handler, &result,
-                              NULL, NULL) == 0) {
+                              NULL, NULL, NULL) == 0) {
                struct hostapd_hw_modes *modes;
 
                nl80211_set_regulatory_flags(drv, &result);
index 3e67fe56954d8fffc26eec04d1c62e0dfc7e441e..183427b2c4461952f838bea7ea06ee0a80f99d95 100644 (file)
@@ -388,7 +388,7 @@ drv_get_connect_fail_reason_code(struct wpa_driver_nl80211_data *drv)
 
        ret = send_and_recv_msgs(drv, msg,
                                 qca_drv_connect_fail_reason_code_handler,
-                                &reason_code, NULL, NULL);
+                                &reason_code, NULL, NULL, NULL);
        if (ret)
                wpa_printf(MSG_DEBUG,
                           "nl80211: Get connect fail reason_code failed: ret=%d (%s)",
index 5bd3e3b46ed4d1a8af06ce6cbe4b055b93d26ba9..736db6406357303dbd9f29150007688d1e200231 100644 (file)
@@ -83,7 +83,7 @@ static int nl80211_get_noise_for_scan_results(
        os_memset(info, 0, sizeof(*info));
        msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
        return send_and_recv_msgs(drv, msg, get_noise_for_scan_results, info,
-                                 NULL, NULL);
+                                 NULL, NULL, NULL);
 }
 
 
@@ -95,7 +95,7 @@ static int nl80211_abort_scan(struct i802_bss *bss)
 
        wpa_printf(MSG_DEBUG, "nl80211: Abort scan");
        msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_ABORT_SCAN);
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: Abort scan failed: ret=%d (%s)",
                           ret, strerror(-ret));
@@ -126,7 +126,7 @@ static int nl80211_abort_vendor_scan(struct wpa_driver_nl80211_data *drv,
 
        nla_nest_end(msg, params);
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        msg = NULL;
        if (ret) {
                wpa_printf(MSG_INFO,
@@ -389,7 +389,7 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss,
                        goto fail;
        }
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        msg = NULL;
        if (ret) {
                wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d "
@@ -642,7 +642,7 @@ int wpa_driver_nl80211_sched_scan(void *priv,
                        params->sched_scan_start_delay))
                goto fail;
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
 
        /* TODO: if we get an error here, we should fall back to normal scan */
 
@@ -679,7 +679,7 @@ int wpa_driver_nl80211_stop_sched_scan(void *priv)
 #endif /* ANDROID */
 
        msg = nl80211_drv_msg(drv, 0, NL80211_CMD_STOP_SCHED_SCAN);
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG,
                           "nl80211: Sched scan stop failed: ret=%d (%s)",
@@ -984,7 +984,8 @@ try_again:
 
        arg.drv = drv;
        arg.res = res;
-       ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg, NULL, NULL,
+                                NULL);
        if (ret == -EAGAIN) {
                count++;
                if (count >= 10) {
@@ -1069,7 +1070,7 @@ void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv)
        msg = nl80211_cmd_msg(drv->first_bss, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
        if (msg)
                send_and_recv_msgs(drv, msg, nl80211_dump_scan_handler, &ctx,
-                                  NULL, NULL);
+                                  NULL, NULL, NULL);
 }
 
 
@@ -1263,7 +1264,7 @@ int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
        nla_nest_end(msg, attr);
 
        ret = send_and_recv_msgs(drv, msg, scan_cookie_handler, &cookie,
-                                NULL, NULL);
+                                NULL, NULL, NULL);
        msg = NULL;
        if (ret) {
                wpa_printf(MSG_DEBUG,
@@ -1326,7 +1327,7 @@ int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len)
 
        nla_nest_end(msg, attr);
 
-       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL, NULL);
        msg = NULL;
        if (ret) {
                wpa_printf(MSG_ERROR,