nl80211: Add support to parse out link from error reply

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>
This commit is contained in:
Benjamin Berg 2023-11-21 01:51:29 +02:00 committed by Jouni Malinen
parent e6eebd0d5c
commit 6ba9b9440b
5 changed files with 225 additions and 151 deletions

File diff suppressed because it is too large Load diff

View 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,

View 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);

View 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)",

View 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,