mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-21 11:22:50 +00:00
Some checks failed
Build OpenWrt/uCentral images / build (cig_wf186h) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf186w) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf188n) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf189) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf196) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cybertan_eww631-a1) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cybertan_eww631-b1) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap101) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap102) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap104) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap105) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap111) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap112) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101-6e) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101e) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101e-6e) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x_2) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x_3) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x_w) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4xe) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4xi) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4xi_w) (push) Has been cancelled
Build OpenWrt/uCentral images / build (indio_um-305ax) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sercomm_ap72tip) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sonicfi_rap630c-311g) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sonicfi_rap630w-211g) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sonicfi_rap630w-311g) (push) Has been cancelled
Build OpenWrt/uCentral images / build (udaya_a6-id2) (push) Has been cancelled
Build OpenWrt/uCentral images / build (udaya_a6-od2) (push) Has been cancelled
Build OpenWrt/uCentral images / build (wallys_dr5018) (push) Has been cancelled
Build OpenWrt/uCentral images / build (wallys_dr6018) (push) Has been cancelled
Build OpenWrt/uCentral images / build (wallys_dr6018-v4) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_ax820) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_ax840) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_fap640) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_fap650) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_fap655) (push) Has been cancelled
Build OpenWrt/uCentral images / trigger-testing (push) Has been cancelled
Build OpenWrt/uCentral images / create-x64_vm-ami (push) Has been cancelled
Signed-off-by: John Crispin <john@phrozen.org>
475 lines
13 KiB
Diff
475 lines
13 KiB
Diff
From ade710c95f8c249b97e87e41b5cebb40c74ee63e Mon Sep 17 00:00:00 2001
|
|
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
|
|
Date: Tue, 10 Oct 2023 15:24:10 +0530
|
|
Subject: [PATCH 1/2] hostapd: add support to use underlying hw_idx for
|
|
multi-hardware under single phy mode
|
|
|
|
During multi-hardware under singly phy scenario, single channel list is
|
|
maintained for a given band which does not clearly tells how many different
|
|
underlying hardwares are being used to form that band. For example - in
|
|
5 GHz split hardware case, two underlying hardwares 5 GHz Low and 5 GHz High
|
|
are being used to enable full 5 GHz band. Now, when channel is selected from
|
|
list of channels, it is possible that a channel can be picked which the
|
|
hardware does not support (lower chanels can be picked for 5 GHz high
|
|
hardware) which is wrong.
|
|
|
|
However, the kernel does tells us about the underlying hardwares and the
|
|
list of supported frequencies.
|
|
|
|
Hence, add support to get the advertised hw_idx and the corresponding list
|
|
of supported frequencies and then decide what is the current hw_idx being
|
|
used.
|
|
|
|
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
|
|
---
|
|
src/ap/ap_drv_ops.c | 9 ++
|
|
src/ap/ap_drv_ops.h | 3 +
|
|
src/ap/hostapd.c | 7 ++
|
|
src/ap/hostapd.h | 4 +
|
|
src/ap/hw_features.c | 77 ++++++++++++++++
|
|
src/ap/hw_features.h | 14 +++
|
|
src/drivers/driver.h | 31 +++++++
|
|
src/drivers/driver_nl80211.c | 1 +
|
|
src/drivers/driver_nl80211.h | 2 +
|
|
src/drivers/driver_nl80211_capa.c | 144 ++++++++++++++++++++++++++++++
|
|
tests/fuzzing/ap-mgmt/ap-mgmt.c | 2 +
|
|
11 files changed, 294 insertions(+)
|
|
|
|
--- a/src/ap/ap_drv_ops.c
|
|
+++ b/src/ap/ap_drv_ops.c
|
|
@@ -1165,3 +1165,12 @@ int hostapd_drv_set_secure_ranging_ctx(s
|
|
return hapd->driver->set_secure_ranging_ctx(hapd->drv_priv, ¶ms);
|
|
}
|
|
#endif /* CONFIG_PASN */
|
|
+
|
|
+struct hostapd_multi_hw_info *
|
|
+hostapd_get_multi_hw_info(struct hostapd_data *hapd, u8 *num_multi_hws)
|
|
+{
|
|
+ if (hapd->driver == NULL ||
|
|
+ hapd->driver->get_multi_hw_info == NULL)
|
|
+ return NULL;
|
|
+ return hapd->driver->get_multi_hw_info(hapd->drv_priv, num_multi_hws);
|
|
+}
|
|
--- a/src/ap/ap_drv_ops.h
|
|
+++ b/src/ap/ap_drv_ops.h
|
|
@@ -462,4 +462,7 @@ static inline int hostapd_drv_link_add(s
|
|
}
|
|
#endif /* CONFIG_IEEE80211BE */
|
|
|
|
+struct hostapd_multi_hw_info *
|
|
+hostapd_get_multi_hw_info(struct hostapd_data *hapd, u8 *num_multi_hws);
|
|
+
|
|
#endif /* AP_DRV_OPS */
|
|
--- a/src/ap/hostapd.c
|
|
+++ b/src/ap/hostapd.c
|
|
@@ -683,6 +683,9 @@ void hostapd_cleanup_iface_partial(struc
|
|
ap_list_deinit(iface);
|
|
sta_track_deinit(iface);
|
|
airtime_policy_update_deinit(iface);
|
|
+ hostapd_free_multi_hw_info(iface->multi_hw_info, iface->num_multi_hws);
|
|
+ iface->multi_hw_info = NULL;
|
|
+ iface->current_hw_info = NULL;
|
|
}
|
|
|
|
|
|
@@ -2466,6 +2469,10 @@ static int hostapd_setup_interface_compl
|
|
hostapd_hw_mode_txt(iface->conf->hw_mode),
|
|
iface->conf->channel, iface->freq);
|
|
|
|
+ if (hostapd_set_current_hw_info(iface, iface->freq)) {
|
|
+ wpa_printf(MSG_ERROR, "Failed to get operating hw mac id");
|
|
+ goto fail;
|
|
+ }
|
|
#ifdef NEED_AP_MLME
|
|
/* Handle DFS only if it is not offloaded to the driver */
|
|
if (!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)) {
|
|
--- a/src/ap/hostapd.h
|
|
+++ b/src/ap/hostapd.h
|
|
@@ -719,6 +719,10 @@ struct hostapd_iface {
|
|
|
|
/* Configured freq of interface is NO_IR */
|
|
bool is_no_ir;
|
|
+
|
|
+ struct hostapd_multi_hw_info *multi_hw_info;
|
|
+ u8 num_multi_hws;
|
|
+ struct hostapd_multi_hw_info *current_hw_info;
|
|
};
|
|
|
|
/* Iterate over all affiliated links in MLD to which @self belongs.
|
|
--- a/src/ap/hw_features.c
|
|
+++ b/src/ap/hw_features.c
|
|
@@ -79,6 +79,8 @@ int hostapd_get_hw_features(struct hosta
|
|
u16 num_modes, flags;
|
|
struct hostapd_hw_modes *modes;
|
|
u8 dfs_domain;
|
|
+ struct hostapd_multi_hw_info *multi_hw_info;
|
|
+ u8 num_multi_hws;
|
|
|
|
if (hostapd_drv_none(hapd))
|
|
return -1;
|
|
@@ -141,6 +143,35 @@ int hostapd_get_hw_features(struct hosta
|
|
}
|
|
}
|
|
|
|
+ multi_hw_info = hostapd_get_multi_hw_info(hapd, &num_multi_hws);
|
|
+ if (multi_hw_info == NULL)
|
|
+ return 0;
|
|
+
|
|
+ hostapd_free_multi_hw_info(iface->multi_hw_info, iface->num_multi_hws);
|
|
+ iface->multi_hw_info = multi_hw_info;
|
|
+ iface->num_multi_hws = num_multi_hws;
|
|
+
|
|
+ wpa_printf(MSG_DEBUG, "Multi Underlying Hardwares Info: ");
|
|
+
|
|
+ for (i = 0; i < num_multi_hws; i++) {
|
|
+ struct hostapd_multi_hw_info *hw_info = &multi_hw_info[i];
|
|
+ char str[1000];
|
|
+ char *pos = str;
|
|
+ char *end = pos + sizeof(str);
|
|
+ int res;
|
|
+
|
|
+ for (j = 0; j < hw_info->num_freqs; j++) {
|
|
+ res = os_snprintf(pos, end - pos, "%d, ", hw_info->freqs[j]);
|
|
+ if (os_snprintf_error(end - pos, res))
|
|
+ break;
|
|
+ pos += res;
|
|
+ }
|
|
+
|
|
+ *pos = '\0';
|
|
+ wpa_printf(MSG_DEBUG, " %d. hw_idx=%u, frequencies: %s",
|
|
+ i + 1, hw_info->hw_idx, str);
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -1431,3 +1462,49 @@ int hostapd_hw_skip_mode(struct hostapd_
|
|
}
|
|
return 0;
|
|
}
|
|
+
|
|
+void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_hw_info,
|
|
+ size_t num_multi_hws)
|
|
+{
|
|
+ size_t i;
|
|
+
|
|
+ if (multi_hw_info == NULL)
|
|
+ return;
|
|
+
|
|
+ for (i = 0; i < num_multi_hws; i++)
|
|
+ os_free(multi_hw_info[i].freqs);
|
|
+
|
|
+ os_free(multi_hw_info);
|
|
+}
|
|
+
|
|
+int hostapd_set_current_hw_info(struct hostapd_iface *iface, u32 oper_freq)
|
|
+{
|
|
+ struct hostapd_multi_hw_info *hw_info;
|
|
+ int i, j;
|
|
+ bool found = false;
|
|
+
|
|
+ if (!iface->num_multi_hws)
|
|
+ return 0;
|
|
+
|
|
+ for (i = 0; i < iface->num_multi_hws; i++) {
|
|
+ hw_info = &iface->multi_hw_info[i];
|
|
+
|
|
+ for (j = 0; j < hw_info->num_freqs; j++) {
|
|
+ if (hw_info->freqs[j] == oper_freq) {
|
|
+ found = true;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (found)
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (i >= iface->num_multi_hws)
|
|
+ return 1;
|
|
+
|
|
+ iface->current_hw_info = hw_info;
|
|
+ wpa_printf(MSG_DEBUG, "Mode: Selected underlying HW: hw_idx=%u",
|
|
+ iface->current_hw_info->hw_idx);
|
|
+ return 0;
|
|
+}
|
|
--- a/src/ap/hw_features.h
|
|
+++ b/src/ap/hw_features.h
|
|
@@ -29,6 +29,9 @@ void hostapd_stop_setup_timers(struct ho
|
|
int hostapd_hw_skip_mode(struct hostapd_iface *iface,
|
|
struct hostapd_hw_modes *mode);
|
|
void hostapd_determine_mode(struct hostapd_iface *iface);
|
|
+void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_macs,
|
|
+ size_t num_multi_hws);
|
|
+int hostapd_set_current_hw_info(struct hostapd_iface *iface, u32 oper_freq);
|
|
#else /* NEED_AP_MLME */
|
|
static inline void
|
|
hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
|
|
@@ -96,6 +99,17 @@ static inline void hostapd_determine_mod
|
|
{
|
|
}
|
|
|
|
+static inline
|
|
+void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_macs,
|
|
+ size_t num_multi_hws)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline int hostapd_set_current_hw_info(struct hostapd_iface *iface,
|
|
+ u32 oper_freq)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
#endif /* NEED_AP_MLME */
|
|
|
|
#endif /* HW_FEATURES_H */
|
|
--- a/src/drivers/driver.h
|
|
+++ b/src/drivers/driver.h
|
|
@@ -320,6 +320,25 @@ struct hostapd_hw_modes {
|
|
s8 psd_values[NL80211_REG_NUM_POWER_MODES];
|
|
};
|
|
|
|
+/**
|
|
+ * struct hostapd_multi_hw_info: Supported multiple underyling hardware info
|
|
+ */
|
|
+struct hostapd_multi_hw_info {
|
|
+ /**
|
|
+ * hw_idx - Hardware index
|
|
+ */
|
|
+ u8 hw_idx;
|
|
+
|
|
+ /**
|
|
+ * num_freqs - Number of entries in the freqs array
|
|
+ */
|
|
+ u8 num_freqs;
|
|
+
|
|
+ /**
|
|
+ * freqs - Array of supported frequencies
|
|
+ */
|
|
+ u32 *freqs;
|
|
+};
|
|
|
|
#define IEEE80211_CAP_ESS 0x0001
|
|
#define IEEE80211_CAP_IBSS 0x0002
|
|
@@ -5225,6 +5244,18 @@ struct wpa_driver_ops {
|
|
*/
|
|
int (*can_share_drv)(void *ctx, struct wpa_init_params *params, void **drv_priv);
|
|
#endif /* CONFIG_IEEE80211BE */
|
|
+
|
|
+ /**
|
|
+ * get_multi_hw_info - Get multi hardware data (hardware IDx and
|
|
+ * supported frequencies)
|
|
+ * @priv: Private driver interface data
|
|
+ * @num_multi_hws: Variable for returning the number of returned hardware
|
|
+ * info data
|
|
+ * Returns: Pointer to allocated mutli hardware data on success or
|
|
+ * %NULL on failure. Caller is responsible for freeing this.
|
|
+ */
|
|
+ struct hostapd_multi_hw_info * (*get_multi_hw_info)(void *priv,
|
|
+ u8 *num_multi_hws);
|
|
};
|
|
|
|
/**
|
|
--- a/src/drivers/driver_nl80211.c
|
|
+++ b/src/drivers/driver_nl80211.c
|
|
@@ -14020,6 +14020,12 @@ free_all:
|
|
}
|
|
#endif /* CONFIG_IEEE80211BE */
|
|
|
|
+static struct hostapd_multi_hw_info *
|
|
+wpa_driver_get_multi_hw_info(void *priv, u8 *num_multi_hws)
|
|
+{
|
|
+ return nl80211_get_multi_hw_info(priv, num_multi_hws);
|
|
+}
|
|
+
|
|
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
|
.name = "nl80211",
|
|
.desc = "Linux nl80211/cfg80211",
|
|
@@ -14179,4 +14185,5 @@ const struct wpa_driver_ops wpa_driver_n
|
|
.get_drv_shared_status = wpa_driver_get_shared_status,
|
|
.can_share_drv = wpa_driver_nl80211_can_share_drv,
|
|
#endif /* CONFIG_IEEE80211BE */
|
|
+ .get_multi_hw_info = wpa_driver_get_multi_hw_info,
|
|
};
|
|
--- a/src/drivers/driver_nl80211.h
|
|
+++ b/src/drivers/driver_nl80211.h
|
|
@@ -368,5 +368,7 @@ int wpa_driver_nl80211_vendor_scan(struc
|
|
struct wpa_driver_scan_params *params);
|
|
int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len);
|
|
int wpa_driver_set_phyname(struct wpa_driver_nl80211_data *drv);
|
|
+struct hostapd_multi_hw_info *
|
|
+nl80211_get_multi_hw_info(void *priv, u8 *num_multi_hws);
|
|
|
|
#endif /* DRIVER_NL80211_H */
|
|
--- a/src/drivers/driver_nl80211_capa.c
|
|
+++ b/src/drivers/driver_nl80211_capa.c
|
|
@@ -1599,6 +1599,12 @@ struct phy_info_arg {
|
|
u8 pwr_mode;
|
|
};
|
|
|
|
+struct phy_multi_hw_info_arg {
|
|
+ int failed;
|
|
+ u8 *num_multi_hws;
|
|
+ struct hostapd_multi_hw_info *multi_hws;
|
|
+};
|
|
+
|
|
static void phy_info_ht_capa(struct hostapd_hw_modes *mode, struct nlattr *capa,
|
|
struct nlattr *ampdu_factor,
|
|
struct nlattr *ampdu_density,
|
|
@@ -2677,6 +2683,144 @@ nl80211_get_hw_feature_data(void *priv,
|
|
}
|
|
|
|
return NULL;
|
|
+}
|
|
+
|
|
+static int phy_multi_hw_info_parse(struct phy_multi_hw_info_arg *multi_hw_info,
|
|
+ struct nlattr *nl_hw_macs)
|
|
+{
|
|
+ struct nlattr *tb_hw[NL80211_MULTI_HW_MAC_ATTR_MAX + 1];
|
|
+ struct nlattr *tb_freq[NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_MAX + 1];
|
|
+ struct nlattr *nl_freq_list;
|
|
+ struct hostapd_multi_hw_info *multi_hws;
|
|
+ int rem_freq_list;
|
|
+ u8 hw_idx, freq_idx = 0, i;
|
|
+ u32 freq[256];
|
|
+
|
|
+ nla_parse(tb_hw, NL80211_MULTI_HW_MAC_ATTR_MAX, nla_data(nl_hw_macs),
|
|
+ nla_len(nl_hw_macs), NULL);
|
|
+
|
|
+ if (!tb_hw[NL80211_MULTI_HW_MAC_ATTR_IDX] ||
|
|
+ !tb_hw[NL80211_MULTI_HW_MAC_ATTR_CHAN_LIST])
|
|
+ return NL_STOP;
|
|
+
|
|
+ hw_idx = nla_get_u8(tb_hw[NL80211_MULTI_HW_MAC_ATTR_IDX]);
|
|
+
|
|
+ nla_for_each_nested(nl_freq_list, tb_hw[NL80211_MULTI_HW_MAC_ATTR_CHAN_LIST],
|
|
+ rem_freq_list)
|
|
+ {
|
|
+ nla_parse(tb_freq, NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_MAX,
|
|
+ nla_data(nl_freq_list), nla_len(nl_freq_list), NULL);
|
|
+
|
|
+ if (!tb_freq[NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_FREQ])
|
|
+ return NL_STOP;
|
|
+
|
|
+ freq[freq_idx++] =
|
|
+ nla_get_u32(tb_freq[NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_FREQ]);
|
|
+ }
|
|
+
|
|
+ multi_hws = os_realloc_array(multi_hw_info->multi_hws,
|
|
+ *multi_hw_info->num_multi_hws + 1,
|
|
+ sizeof(*multi_hws));
|
|
+ if (!multi_hws) {
|
|
+ multi_hw_info->failed = 1;
|
|
+ return NL_STOP;
|
|
+ }
|
|
+
|
|
+ multi_hw_info->multi_hws = multi_hws;
|
|
+
|
|
+ multi_hws = &multi_hw_info->multi_hws[*(multi_hw_info->num_multi_hws)];
|
|
+
|
|
+ multi_hws->hw_idx = hw_idx;
|
|
+ multi_hws->num_freqs = freq_idx;
|
|
+
|
|
+ multi_hws->freqs = os_calloc(multi_hws->num_freqs, sizeof(u32));
|
|
+ if (!multi_hws->freqs) {
|
|
+ multi_hw_info->failed = 1;
|
|
+ return NL_STOP;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < multi_hws->num_freqs; i++)
|
|
+ multi_hws->freqs[i] = freq[i];
|
|
+
|
|
+ *(multi_hw_info->num_multi_hws) += 1;
|
|
+
|
|
+ return NL_OK;
|
|
+}
|
|
+
|
|
+static int phy_multi_hw_info_handler(struct nl_msg *msg, void *arg)
|
|
+{
|
|
+ struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
|
|
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
|
|
+ struct phy_multi_hw_info_arg *multi_hw_info = arg;
|
|
+ struct nlattr *nl_hw_macs;
|
|
+ int rem_hw_macs, res;
|
|
+
|
|
+ nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
|
|
+ genlmsg_attrlen(gnlh, 0), NULL);
|
|
+
|
|
+ if (!tb_msg[NL80211_ATTR_MULTI_HW_MACS])
|
|
+ return NL_SKIP;
|
|
+
|
|
+ nla_for_each_nested(nl_hw_macs, tb_msg[NL80211_ATTR_MULTI_HW_MACS],
|
|
+ rem_hw_macs)
|
|
+ {
|
|
+ res = phy_multi_hw_info_parse(multi_hw_info, nl_hw_macs);
|
|
+ if (res != NL_OK)
|
|
+ return res;
|
|
+ }
|
|
+
|
|
+ return NL_SKIP;
|
|
+}
|
|
+
|
|
+struct hostapd_multi_hw_info *
|
|
+nl80211_get_multi_hw_info(void *priv, u8 *num_multi_hws)
|
|
+{
|
|
+ u32 feat;
|
|
+ struct i802_bss *bss = priv;
|
|
+ struct wpa_driver_nl80211_data *drv = bss->drv;
|
|
+ int nl_flags = 0;
|
|
+ struct nl_msg *msg;
|
|
+ struct phy_multi_hw_info_arg result = {
|
|
+ .failed = 0,
|
|
+ .num_multi_hws = num_multi_hws,
|
|
+ .multi_hws = NULL,
|
|
+ };
|
|
+
|
|
+ *num_multi_hws = 0;
|
|
+
|
|
+ if (!drv->has_capability)
|
|
+ return NULL;
|
|
+
|
|
+ if (!(drv->capa.flags2 & WPA_DRIVER_FLAGS2_MLO))
|
|
+ return NULL;
|
|
+
|
|
+ feat = get_nl80211_protocol_features(drv);
|
|
+ if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
|
|
+ nl_flags = NLM_F_DUMP;
|
|
+ if (!(msg = nl80211_cmd_msg(bss, nl_flags, NL80211_CMD_GET_WIPHY)) ||
|
|
+ nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP)) {
|
|
+ nlmsg_free(msg);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (send_and_recv_msgs(drv, msg, phy_multi_hw_info_handler, &result,
|
|
+ NULL, NULL) == 0) {
|
|
+ if (result.failed) {
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; result.num_multi_hws && i < *num_multi_hws; i++)
|
|
+ os_free(result.multi_hws[i].freqs);
|
|
+
|
|
+ os_free(result.multi_hws);
|
|
+ *num_multi_hws = 0;
|
|
+
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ return result.multi_hws;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
}
|
|
|
|
#ifdef CONFIG_IEEE80211BE
|
|
--- a/tests/fuzzing/ap-mgmt/ap-mgmt.c
|
|
+++ b/tests/fuzzing/ap-mgmt/ap-mgmt.c
|
|
@@ -156,6 +156,8 @@ int LLVMFuzzerTestOneInput(const uint8_t
|
|
hostapd_free_stas(&ctx.hapd);
|
|
hostapd_free_hw_features(ctx.hapd.iface->hw_features,
|
|
ctx.hapd.iface->num_hw_features);
|
|
+ hostapd_free_multi_hw_info(ctx.hapd.iface->multi_hw_info,
|
|
+ ctx.hapd.iface->num_multi_hws);
|
|
|
|
fail:
|
|
hostapd_config_free(ctx.hapd.iconf);
|