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>
424 lines
13 KiB
Diff
424 lines
13 KiB
Diff
From b4bd16074a9655c0b40e462325c6946c0c3f99c4 Mon Sep 17 00:00:00 2001
|
|
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
|
|
Date: Fri, 20 Oct 2023 15:39:32 +0530
|
|
Subject: [PATCH] hostapd: re-assign driver context if existing ML partner is
|
|
found
|
|
|
|
Currently multiple driver contexts were maintained for a single interface
|
|
in certain co-hosted situations. For instance - 5 GHz SLO and 5 GHz +
|
|
6 GHz MLD. In this case, if 6 GHz config is passed first then driver would
|
|
be created. And when 5 GHz config is parsed, since bss[0] is SLO, there
|
|
won't be any partner and hence again driver would be created. This makes
|
|
5 GHz interface to have two different drivers. During de-initialization,
|
|
proper deinitialization will not happen and a few times seg fault could
|
|
be seen.
|
|
|
|
Hence to avoid this situation, try to maintain single driver if possible.
|
|
|
|
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
|
|
---
|
|
src/ap/ap_drv_ops.h | 9 +++++
|
|
src/ap/hostapd.c | 1 +
|
|
src/drivers/driver.h | 10 +++++
|
|
src/drivers/driver_nl80211.c | 71 ++++++++++++++++++++++++++++++++++++
|
|
4 files changed, 91 insertions(+)
|
|
|
|
--- a/hostapd/main.c
|
|
+++ b/hostapd/main.c
|
|
@@ -249,6 +249,15 @@ static int hostapd_driver_init(struct ho
|
|
|
|
params.own_addr = hapd->own_addr;
|
|
|
|
+#ifdef CONFIG_IEEE80211BE
|
|
+ if (hapd->driver->can_share_drv &&
|
|
+ !hapd->driver->can_share_drv(hapd, ¶ms, &hapd->drv_priv)) {
|
|
+ hapd->interface_added = 1;
|
|
+ os_free(params.bridge);
|
|
+ goto pre_setup_mld;
|
|
+ }
|
|
+#endif /* CONFIG_IEEE80211BE */
|
|
+
|
|
hapd->drv_priv = hapd->driver->hapd_init(hapd, ¶ms);
|
|
if (hapd->conf->is_bonded_iface_enabled)
|
|
hostapd_mld_update_bridge_conn(hapd->conf->bridge, hapd->conf->iface);
|
|
@@ -261,6 +270,7 @@ static int hostapd_driver_init(struct ho
|
|
}
|
|
|
|
#ifdef CONFIG_IEEE80211BE
|
|
+pre_setup_mld:
|
|
/*
|
|
* This is the first interface added to the AP MLD, so have the
|
|
* interface hardware address be the MLD address and set a link address
|
|
--- a/src/ap/hostapd.c
|
|
+++ b/src/ap/hostapd.c
|
|
@@ -523,7 +523,10 @@ void hostapd_free_hapd_data(struct hosta
|
|
|
|
authsrv_deinit(hapd);
|
|
|
|
- if (hapd->interface_added) {
|
|
+ /* For single drv, first bss would have interface_added flag set. Don't
|
|
+ * remove interface now. driver deinit part will take care
|
|
+ */
|
|
+ if (hapd->interface_added && hapd->iface->bss[0] != hapd) {
|
|
hapd->interface_added = 0;
|
|
if (hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) {
|
|
wpa_printf(MSG_WARNING,
|
|
@@ -3216,25 +3219,26 @@ static void hostapd_cleanup_driver(const
|
|
ap_mld = !!iface->bss[0]->conf->mld_ap;
|
|
#endif /* CONFIG_IEEE80211BE */
|
|
|
|
- /* In case of non-ML operation, de-init. But, if ML operation exist, then
|
|
- * even if thats the last BSS in the interface, the driver (drv) could
|
|
- * be in use for a different MLD. Hence, need to check if drv is still
|
|
- * being used by some other bss before de-initiallizing
|
|
- */
|
|
- if (!ap_mld)
|
|
- driver->hapd_deinit(drv_priv);
|
|
- else if (hostapd_mld_is_first_bss(iface->bss[0]) &&
|
|
- driver->get_drv_shared_status &&
|
|
- !driver->get_drv_shared_status(drv_priv, iface->bss[0])) {
|
|
+ if (driver->get_drv_shared_status &&
|
|
+ !driver->get_drv_shared_status(drv_priv, iface->bss[0])) {
|
|
driver->hapd_deinit(drv_priv);
|
|
- } else if (hostapd_if_link_remove(iface->bss[0],
|
|
- WPA_IF_AP_BSS,
|
|
- iface->bss[0]->conf->iface,
|
|
- iface->bss[0]->mld_link_id)) {
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
+ if (ap_mld) {
|
|
+ if (hostapd_if_link_remove(iface->bss[0],
|
|
+ WPA_IF_AP_BSS,
|
|
+ iface->bss[0]->conf->iface,
|
|
+ iface->bss[0]->mld_link_id))
|
|
+ wpa_printf(MSG_WARNING, "Failed to remove link BSS interface %s",
|
|
+ iface->bss[0]->conf->iface);
|
|
+ } else if (hostapd_if_remove(iface->bss[0], WPA_IF_AP_BSS,
|
|
+ iface->bss[0]->conf->iface)) {
|
|
wpa_printf(MSG_WARNING, "Failed to remove BSS interface %s",
|
|
iface->bss[0]->conf->iface);
|
|
}
|
|
|
|
+exit:
|
|
iface->bss[0]->drv_priv = NULL;
|
|
}
|
|
|
|
--- a/src/drivers/driver.h
|
|
+++ b/src/drivers/driver.h
|
|
@@ -5210,6 +5210,20 @@ struct wpa_driver_ops {
|
|
* Returns: True if it is being used or else False.
|
|
*/
|
|
bool (*get_drv_shared_status)(void *priv, void *bss_ctx);
|
|
+
|
|
+ /**
|
|
+ * can_share_drv - Check if already a drv exist in the same global driver
|
|
+ * which can be shared instead of creating a new drv.
|
|
+ * Used during single wiphy operation.
|
|
+ *
|
|
+ * @ctx: Pointer to hostapd context
|
|
+ * @params: Configuration for the driver wrapper
|
|
+ * @drv_priv: Pointer for overwriting the driver context or %NULL if
|
|
+ * cant' find a shared drv
|
|
+ *
|
|
+ * Returns: 0 on success, -1 on failure
|
|
+ */
|
|
+ int (*can_share_drv)(void *ctx, struct wpa_init_params *params, void **drv_priv);
|
|
#endif /* CONFIG_IEEE80211BE */
|
|
};
|
|
|
|
--- a/src/drivers/driver_nl80211.c
|
|
+++ b/src/drivers/driver_nl80211.c
|
|
@@ -2916,10 +2916,12 @@ wpa_driver_nl80211_finish_drv_init(struc
|
|
if (!bss->if_dynamic && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
|
|
bss->static_ap = 1;
|
|
|
|
- if (first &&
|
|
- nl80211_get_ifmode(bss) != NL80211_IFTYPE_P2P_DEVICE &&
|
|
- linux_iface_up(drv->global->ioctl_sock, bss->ifname) > 0)
|
|
- drv->start_iface_up = 1;
|
|
+ if (nl80211_get_ifmode(bss) != NL80211_IFTYPE_P2P_DEVICE &&
|
|
+ linux_iface_up(drv->global->ioctl_sock, bss->ifname) > 0) {
|
|
+ if (first)
|
|
+ drv->start_iface_up = 1;
|
|
+ bss->start_iface_up = 1;
|
|
+ }
|
|
|
|
if (wpa_driver_nl80211_capa(drv))
|
|
return -1;
|
|
@@ -2936,8 +2938,11 @@ wpa_driver_nl80211_finish_drv_init(struc
|
|
set_addr)))
|
|
return -1;
|
|
|
|
- if (first && nl80211_get_ifmode(bss) == NL80211_IFTYPE_STATION)
|
|
- drv->start_mode_sta = 1;
|
|
+ if (nl80211_get_ifmode(bss) == NL80211_IFTYPE_STATION) {
|
|
+ if (first)
|
|
+ drv->start_mode_sta = 1;
|
|
+ bss->start_mode_sta = 1;
|
|
+ }
|
|
|
|
if (drv->hostapd || bss->static_ap)
|
|
nlmode = NL80211_IFTYPE_AP;
|
|
@@ -8907,6 +8912,7 @@ static int wpa_driver_nl80211_if_remove(
|
|
{
|
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
|
int ifindex = if_nametoindex(ifname);
|
|
+ enum nl80211_iftype nlmode;
|
|
|
|
wpa_printf(MSG_DEBUG, "nl80211: %s(type=%d ifname=%s) ifindex=%d added_if=%d",
|
|
__func__, type, ifname, ifindex, bss->added_if);
|
|
@@ -8945,12 +8951,20 @@ static int wpa_driver_nl80211_if_remove(
|
|
for (tbss = drv->first_bss; tbss; tbss = tbss->next) {
|
|
if (tbss->next == bss) {
|
|
tbss->next = bss->next;
|
|
- /* Unsubscribe management frames */
|
|
- nl80211_teardown_ap(bss);
|
|
+ bss->in_deinit = 1;
|
|
nl80211_remove_links(bss);
|
|
- nl80211_destroy_bss(bss);
|
|
+ nlmode = drv->nlmode;
|
|
if (!bss->added_if)
|
|
i802_set_iface_flags(bss, 0);
|
|
+ if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE &&
|
|
+ bss->start_mode_sta)
|
|
+ wpa_driver_nl80211_set_mode(bss,
|
|
+ NL80211_IFTYPE_STATION);
|
|
+ else
|
|
+ /* Unsubscribe management frames */
|
|
+ nl80211_teardown_ap(bss);
|
|
+ nl80211_destroy_bss(bss);
|
|
+ drv->nlmode = nlmode;
|
|
os_free(bss);
|
|
bss = NULL;
|
|
break;
|
|
@@ -8960,16 +8974,29 @@ static int wpa_driver_nl80211_if_remove(
|
|
wpa_printf(MSG_INFO, "nl80211: %s - could not find "
|
|
"BSS %p in the list", __func__, bss);
|
|
} else {
|
|
- wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context");
|
|
- nl80211_teardown_ap(bss);
|
|
+ bss->in_deinit = 1;
|
|
nl80211_remove_links(bss);
|
|
- nl80211_destroy_bss(bss);
|
|
- if (!bss->added_if)
|
|
+ nlmode = drv->nlmode;
|
|
+ if (!bss->start_iface_up)
|
|
i802_set_iface_flags(bss, 0);
|
|
+ if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE &&
|
|
+ bss->start_mode_sta)
|
|
+ wpa_driver_nl80211_set_mode(bss,
|
|
+ NL80211_IFTYPE_STATION);
|
|
+ else
|
|
+ nl80211_teardown_ap(bss);
|
|
+ nl80211_destroy_bss(bss);
|
|
+ drv->nlmode = nlmode;
|
|
+
|
|
+ wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context");
|
|
if (drv->first_bss->next) {
|
|
drv->first_bss = drv->first_bss->next;
|
|
drv->ctx = drv->first_bss->ctx;
|
|
+ drv->ifindex = drv->first_bss->ifindex;
|
|
+ drv->start_iface_up = drv->first_bss->start_iface_up;
|
|
+ drv->start_mode_sta = drv->first_bss->start_mode_sta;
|
|
os_free(bss);
|
|
+ bss = NULL;
|
|
} else {
|
|
wpa_printf(MSG_DEBUG, "nl80211: No second BSS to reassign context to");
|
|
}
|
|
@@ -13884,6 +13911,120 @@ static bool wpa_driver_get_shared_status
|
|
return false;
|
|
}
|
|
|
|
+#ifdef CONFIG_IEEE80211BE
|
|
+static bool wpa_driver_nl80211_name_match(struct wpa_driver_nl80211_data *drv,
|
|
+ struct wpa_driver_nl80211_data **match_drv)
|
|
+{
|
|
+ struct wpa_driver_nl80211_data *drv_itr, *tmp;
|
|
+
|
|
+ dl_list_for_each_safe(drv_itr, tmp, &drv->global->interfaces,
|
|
+ struct wpa_driver_nl80211_data, list) {
|
|
+ if (os_strcmp(drv_itr->phyname, drv->phyname) == 0) {
|
|
+ if (match_drv)
|
|
+ *match_drv = drv_itr;
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
+static int wpa_driver_nl80211_can_share_drv(void *ctx,
|
|
+ struct wpa_init_params *params,
|
|
+ void **drv_priv)
|
|
+{
|
|
+ struct wpa_driver_nl80211_data *drv, *match_drv;
|
|
+ struct i802_bss *bss, *new_bss;
|
|
+ char force_ifname[IFNAMSIZ];
|
|
+ u8 if_addr[ETH_ALEN];
|
|
+ const u8 *addr;
|
|
+ int ret = -1;
|
|
+
|
|
+ /* create a dummy drv to read the phyname */
|
|
+ if (params->global_priv == NULL)
|
|
+ return ret;
|
|
+ drv = os_zalloc(sizeof(*drv));
|
|
+
|
|
+ if (drv == NULL)
|
|
+ return ret;
|
|
+ drv->global = params->global_priv;
|
|
+ drv->ctx = ctx;
|
|
+
|
|
+ drv->first_bss = os_zalloc(sizeof(*drv->first_bss));
|
|
+ if (!drv->first_bss) {
|
|
+ os_free(drv);
|
|
+ return ret;
|
|
+ }
|
|
+ bss = drv->first_bss;
|
|
+ bss->drv = drv;
|
|
+ bss->ctx = ctx;
|
|
+
|
|
+ os_strlcpy(bss->ifname, params->ifname, sizeof(bss->ifname));
|
|
+
|
|
+ if (nl80211_init_bss(bss))
|
|
+ goto free_all;
|
|
+
|
|
+ drv->ifindex = if_nametoindex(bss->ifname);
|
|
+ bss->ifindex = drv->ifindex;
|
|
+
|
|
+ if (wpa_driver_set_phyname(drv))
|
|
+ goto free_all;
|
|
+
|
|
+ match_drv = NULL;
|
|
+ if (!wpa_driver_nl80211_name_match(drv, &match_drv))
|
|
+ goto free_all;
|
|
+
|
|
+ if (!match_drv)
|
|
+ goto free_all;
|
|
+
|
|
+ wpa_printf(MSG_DEBUG, "nl80211: Driver for phy %s already exist. Using that.",
|
|
+ match_drv->phyname);
|
|
+
|
|
+ /* store the original state and mode */
|
|
+ if (nl80211_get_ifmode(bss) != NL80211_IFTYPE_P2P_DEVICE &&
|
|
+ linux_iface_up(match_drv->global->ioctl_sock, bss->ifname) > 0)
|
|
+ bss->start_iface_up = 1;
|
|
+
|
|
+ if (nl80211_get_ifmode(bss) == NL80211_IFTYPE_STATION)
|
|
+ bss->start_mode_sta = 1;
|
|
+
|
|
+ addr = params->bssid;
|
|
+ if (wpa_driver_nl80211_if_add(match_drv->first_bss, WPA_IF_AP_BSS,
|
|
+ params->ifname, addr, ctx, drv_priv,
|
|
+ force_ifname, if_addr,
|
|
+ params->num_bridge && params->bridge[0] ? params->bridge[0] : NULL,
|
|
+ 0, 1)) {
|
|
+ wpa_printf(MSG_DEBUG, "nl80211: Failed to add BSS. Expect issues!");
|
|
+ goto free_all;
|
|
+ }
|
|
+
|
|
+ if (!addr)
|
|
+ os_memcpy(params->own_addr, if_addr, ETH_ALEN);
|
|
+ else
|
|
+ os_memcpy(params->own_addr, addr, ETH_ALEN);
|
|
+
|
|
+ /* retain the state and mode in newly created bss. This will be used during
|
|
+ * driver deinit and reassigning first bss to this bss
|
|
+ */
|
|
+ new_bss = *drv_priv;
|
|
+ new_bss->start_iface_up = bss->start_iface_up;
|
|
+ new_bss->start_mode_sta = bss->start_mode_sta;
|
|
+
|
|
+ /* This flag was set in wpa_driver_nl80211_if_add(), but it was already
|
|
+ * present, hence reset it back. This would be useful during deinit flow
|
|
+ */
|
|
+ new_bss->added_if = 0;
|
|
+
|
|
+ ret = 0;
|
|
+
|
|
+free_all:
|
|
+ nl80211_destroy_bss(bss);
|
|
+ os_free(bss);
|
|
+ os_free(drv);
|
|
+ return ret;
|
|
+}
|
|
+#endif /* CONFIG_IEEE80211BE */
|
|
+
|
|
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
|
.name = "nl80211",
|
|
.desc = "Linux nl80211/cfg80211",
|
|
@@ -14041,5 +14182,6 @@ const struct wpa_driver_ops wpa_driver_n
|
|
#ifdef CONFIG_IEEE80211BE
|
|
.if_link_remove = driver_nl80211_if_link_remove,
|
|
.get_drv_shared_status = wpa_driver_get_shared_status,
|
|
+ .can_share_drv = wpa_driver_nl80211_can_share_drv,
|
|
#endif /* CONFIG_IEEE80211BE */
|
|
};
|
|
--- a/src/drivers/driver_nl80211.h
|
|
+++ b/src/drivers/driver_nl80211.h
|
|
@@ -82,6 +82,8 @@ struct i802_bss {
|
|
unsigned int added_if:1;
|
|
unsigned int static_ap:1;
|
|
unsigned int use_nl_connect:1;
|
|
+ unsigned int start_iface_up:1;
|
|
+ unsigned int start_mode_sta:1;
|
|
|
|
u8 addr[ETH_ALEN];
|
|
u8 prev_addr[ETH_ALEN];
|
|
@@ -365,5 +367,6 @@ int wpa_driver_nl80211_abort_scan(void *
|
|
int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
|
|
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);
|
|
|
|
#endif /* DRIVER_NL80211_H */
|
|
--- a/src/drivers/driver_nl80211_capa.c
|
|
+++ b/src/drivers/driver_nl80211_capa.c
|
|
@@ -2678,3 +2678,46 @@ nl80211_get_hw_feature_data(void *priv,
|
|
|
|
return NULL;
|
|
}
|
|
+
|
|
+#ifdef CONFIG_IEEE80211BE
|
|
+static int wpa_driver_get_wiphy_name(struct nl_msg *msg, void *arg)
|
|
+{
|
|
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
|
|
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
|
|
+ struct wpa_driver_nl80211_data *drv = arg;
|
|
+
|
|
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
|
|
+ genlmsg_attrlen(gnlh, 0), NULL);
|
|
+
|
|
+ if (!tb[NL80211_ATTR_WIPHY_NAME])
|
|
+ return NL_SKIP;
|
|
+
|
|
+ os_strlcpy(drv->phyname, nla_get_string(tb[NL80211_ATTR_WIPHY_NAME]),
|
|
+ sizeof(drv->phyname));
|
|
+
|
|
+ return NL_SKIP;
|
|
+}
|
|
+
|
|
+int wpa_driver_set_phyname(struct wpa_driver_nl80211_data *drv)
|
|
+{
|
|
+ struct nl_msg *msg;
|
|
+ u32 feat, nl_flags;
|
|
+
|
|
+ feat = get_nl80211_protocol_features(drv);
|
|
+ if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
|
|
+ nl_flags = NLM_F_DUMP;
|
|
+
|
|
+ if (!(msg = nl80211_cmd_msg(drv->first_bss, nl_flags,
|
|
+ NL80211_CMD_GET_WIPHY)) ||
|
|
+ nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP)) {
|
|
+ nlmsg_free(msg);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (send_and_recv_msgs(drv, msg, wpa_driver_get_wiphy_name, drv,
|
|
+ NULL, NULL))
|
|
+ return -1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+#endif /* CONFIG_IEEE80211BE */
|