From 721008f1c3b1c2c58934a950f49d5ca85c4cc3eb Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 1 Mar 2022 05:42:43 +0200 Subject: [PATCH 1/3] linux-headers: add nl80211-vnd-intel.h kernel header Take from include/uapi/linux/nl80211-vnd-intel.h Linux 5.17-rc5, cfb92440ee71adcc2105b0890bb01ac3cddb8507 March 1, 2022 --- Makefile.am | 1 + src/linux-headers/nl80211-vnd-intel.h | 106 ++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 src/linux-headers/nl80211-vnd-intel.h diff --git a/Makefile.am b/Makefile.am index 1c85805c96..4d9c4e7a7f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -588,6 +588,7 @@ src_libnm_platform_libnm_platform_la_SOURCES = \ \ src/linux-headers/ethtool.h \ src/linux-headers/nl802154.h \ + src/linux-headers/nl80211-vnd-intel.h \ \ src/libnm-platform/nm-linux-platform.c \ src/libnm-platform/nm-linux-platform.h \ diff --git a/src/linux-headers/nl80211-vnd-intel.h b/src/linux-headers/nl80211-vnd-intel.h new file mode 100644 index 0000000000..4ed7d0b245 --- /dev/null +++ b/src/linux-headers/nl80211-vnd-intel.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Copyright (C) 2012-2014, 2018-2021 Intel Corporation + * Copyright (C) 2013-2015 Intel Mobile Communications GmbH + * Copyright (C) 2016-2017 Intel Deutschland GmbH + */ +#ifndef __VENDOR_CMD_INTEL_H__ +#define __VENDOR_CMD_INTEL_H__ + +#define INTEL_OUI 0x001735 + +/** + * enum iwl_mvm_vendor_cmd - supported vendor commands + * @IWL_MVM_VENDOR_CMD_GET_CSME_CONN_INFO: reports CSME connection info. + * @IWL_MVM_VENDOR_CMD_HOST_GET_OWNERSHIP: asks for ownership on the device. + * This is useful when the CSME firmware owns the device and the kernel + * wants to use it. In case the CSME firmware has no connection active the + * kernel will manage on its own to get ownership of the device. + * When the CSME firmware has an active connection, the user space + * involvement is required. The kernel will assert the RFKILL signal with + * the "device not owned" reason so that nobody can touch the device. Then + * the user space can run the following flow to be able to get connected + * to the very same AP the CSME firmware is currently connected to: + * + * 1) The user space (NetworkManager) boots and sees that the device is + * in RFKILL because the host doesn't own the device + * 2) The user space asks the kernel what AP the CSME firmware is + * connected to (with %IWL_MVM_VENDOR_CMD_GET_CSME_CONN_INFO) + * 3) The user space checks if it has a profile that matches the reply + * from the CSME firmware + * 4) The user space installs a network to the wpa_supplicant with a + * specific BSSID and a specific frequency + * 5) The user space prevents any type of full scan + * 6) The user space asks iwlmei to request ownership on the device (with + * this command) + * 7) iwlmei requests ownership from the CSME firmware + * 8) The CSME firmware grants ownership + * 9) iwlmei tells iwlwifi to lift the RFKILL + * 10) RFKILL OFF is reported to user space + * 11) The host boots the device, loads the firwmare, and connects to a + * specific BSSID without scanning including IP as fast as it can + * 12) The host reports to the CSME firmware that there is a connection + * 13) The TCP connection is preserved and the host has connectivity + * + * @IWL_MVM_VENDOR_CMD_ROAMING_FORBIDDEN_EVENT: notifies if roaming is allowed. + * It contains a &IWL_MVM_VENDOR_ATTR_ROAMING_FORBIDDEN and a + * &IWL_MVM_VENDOR_ATTR_VIF_ADDR attributes. + */ + +enum iwl_mvm_vendor_cmd { + IWL_MVM_VENDOR_CMD_GET_CSME_CONN_INFO = 0x2d, + IWL_MVM_VENDOR_CMD_HOST_GET_OWNERSHIP = 0x30, + IWL_MVM_VENDOR_CMD_ROAMING_FORBIDDEN_EVENT = 0x32, +}; + +enum iwl_vendor_auth_akm_mode { + IWL_VENDOR_AUTH_OPEN, + IWL_VENDOR_AUTH_RSNA = 0x6, + IWL_VENDOR_AUTH_RSNA_PSK, + IWL_VENDOR_AUTH_SAE = 0x9, + IWL_VENDOR_AUTH_MAX, +}; + +/** + * enum iwl_mvm_vendor_attr - attributes used in vendor commands + * @__IWL_MVM_VENDOR_ATTR_INVALID: attribute 0 is invalid + * @IWL_MVM_VENDOR_ATTR_VIF_ADDR: interface MAC address + * @IWL_MVM_VENDOR_ATTR_ADDR: MAC address + * @IWL_MVM_VENDOR_ATTR_SSID: SSID (binary attribute, 0..32 octets) + * @IWL_MVM_VENDOR_ATTR_STA_CIPHER: the cipher to use for the station with the + * mac address specified in &IWL_MVM_VENDOR_ATTR_ADDR. + * @IWL_MVM_VENDOR_ATTR_ROAMING_FORBIDDEN: u8 attribute. Indicates whether + * roaming is forbidden or not. Value 1 means roaming is forbidden, + * 0 mean roaming is allowed. + * @IWL_MVM_VENDOR_ATTR_AUTH_MODE: u32 attribute. Authentication mode type + * as specified in &enum iwl_vendor_auth_akm_mode. + * @IWL_MVM_VENDOR_ATTR_CHANNEL_NUM: u8 attribute. Contains channel number. + * @IWL_MVM_VENDOR_ATTR_BAND: u8 attribute. + * 0 for 2.4 GHz band, 1 for 5.2GHz band and 2 for 6GHz band. + * @IWL_MVM_VENDOR_ATTR_COLLOC_CHANNEL: u32 attribute. Channel number of + * collocated AP. Relevant for 6GHz AP info. + * @IWL_MVM_VENDOR_ATTR_COLLOC_ADDR: MAC address of a collocated AP. + * Relevant for 6GHz AP info. + * + * @NUM_IWL_MVM_VENDOR_ATTR: number of vendor attributes + * @MAX_IWL_MVM_VENDOR_ATTR: highest vendor attribute number + + */ +enum iwl_mvm_vendor_attr { + __IWL_MVM_VENDOR_ATTR_INVALID = 0x00, + IWL_MVM_VENDOR_ATTR_VIF_ADDR = 0x02, + IWL_MVM_VENDOR_ATTR_ADDR = 0x0a, + IWL_MVM_VENDOR_ATTR_SSID = 0x3d, + IWL_MVM_VENDOR_ATTR_STA_CIPHER = 0x51, + IWL_MVM_VENDOR_ATTR_ROAMING_FORBIDDEN = 0x64, + IWL_MVM_VENDOR_ATTR_AUTH_MODE = 0x65, + IWL_MVM_VENDOR_ATTR_CHANNEL_NUM = 0x66, + IWL_MVM_VENDOR_ATTR_BAND = 0x69, + IWL_MVM_VENDOR_ATTR_COLLOC_CHANNEL = 0x70, + IWL_MVM_VENDOR_ATTR_COLLOC_ADDR = 0x71, + + NUM_IWL_MVM_VENDOR_ATTR, + MAX_IWL_MVM_VENDOR_ATTR = NUM_IWL_MVM_VENDOR_ATTR - 1, +}; + +#endif /* __VENDOR_CMD_INTEL_H__ */ From 526c4b329332c1607732a9ca17fe11b0adeacf14 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 28 Feb 2022 18:46:12 +0200 Subject: [PATCH 2/3] platform: add the plumbing to get the CSME connection info This allows to fetch the information about the AP that CSME if connected to. It'll allow us to connect to the exact same AP and shaving off the scan from the connection, improving the connection time. --- src/libnm-platform/nm-linux-platform.c | 9 ++ src/libnm-platform/nm-platform.c | 12 +++ src/libnm-platform/nm-platform.h | 14 +++ .../wifi/nm-wifi-utils-nl80211.c | 87 +++++++++++++++++++ .../wifi/nm-wifi-utils-private.h | 3 + src/libnm-platform/wifi/nm-wifi-utils.c | 11 +++ src/libnm-platform/wifi/nm-wifi-utils.h | 4 + 7 files changed, 140 insertions(+) diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index 19a661b9f7..1c14c08b4a 100644 --- a/src/libnm-platform/nm-linux-platform.c +++ b/src/libnm-platform/nm-linux-platform.c @@ -8536,6 +8536,14 @@ wifi_set_wake_on_wlan(NMPlatform *platform, int ifindex, _NMSettingWirelessWakeO return nm_wifi_utils_set_wake_on_wlan(wifi_data, wowl); } +static gboolean +wifi_get_csme_conn_info(NMPlatform *platform, int ifindex, NMPlatformCsmeConnInfo *out_conn_info) +{ + WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); + + return nm_wifi_utils_get_csme_conn_info(wifi_data, out_conn_info); +} + /*****************************************************************************/ static gboolean @@ -9954,6 +9962,7 @@ nm_linux_platform_class_init(NMLinuxPlatformClass *klass) platform_class->wifi_indicate_addressing_running = wifi_indicate_addressing_running; platform_class->wifi_get_wake_on_wlan = wifi_get_wake_on_wlan; platform_class->wifi_set_wake_on_wlan = wifi_set_wake_on_wlan; + platform_class->wifi_get_csme_conn_info = wifi_get_csme_conn_info; platform_class->mesh_get_channel = mesh_get_channel; platform_class->mesh_set_channel = mesh_set_channel; diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index f76cdfcf78..52dc4779d2 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -3061,6 +3061,18 @@ nm_platform_wifi_set_wake_on_wlan(NMPlatform *self, int ifindex, _NMSettingWirel return klass->wifi_set_wake_on_wlan(self, ifindex, wowl); } +gboolean +nm_platform_wifi_get_csme_conn_info(NMPlatform *self, + int ifindex, + NMPlatformCsmeConnInfo *out_conn_info) +{ + _CHECK_SELF(self, klass, FALSE); + + g_return_val_if_fail(ifindex > 0, FALSE); + + return klass->wifi_get_csme_conn_info(self, ifindex, out_conn_info); +} + guint32 nm_platform_mesh_get_channel(NMPlatform *self, int ifindex) { diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h index 8965336045..87441026c3 100644 --- a/src/libnm-platform/nm-platform.h +++ b/src/libnm-platform/nm-platform.h @@ -1017,6 +1017,14 @@ typedef void (*NMPlatformAsyncCallback)(GError *error, gpointer user_data); /*****************************************************************************/ +typedef struct _NMPlatformCsmeConnInfo { + guint8 ssid[32]; + guint32 channel; + NMEtherAddr addr; + guint8 sta_cipher; + guint8 auth_mode; +} NMPlatformCsmeConnInfo; + typedef enum { NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE, @@ -1204,6 +1212,9 @@ typedef struct { gboolean (*wifi_set_wake_on_wlan)(NMPlatform *self, int ifindex, _NMSettingWirelessWakeOnWLan wowl); + gboolean (*wifi_get_csme_conn_info)(NMPlatform *self, + int ifindex, + NMPlatformCsmeConnInfo *out_conn_info); guint32 (*mesh_get_channel)(NMPlatform *self, int ifindex); gboolean (*mesh_set_channel)(NMPlatform *self, int ifindex, guint32 channel); @@ -2028,6 +2039,9 @@ void nm_platform_wifi_indicate_addressing_running(NMPlatform *self, int ifindex, _NMSettingWirelessWakeOnWLan nm_platform_wifi_get_wake_on_wlan(NMPlatform *self, int ifindex); gboolean nm_platform_wifi_set_wake_on_wlan(NMPlatform *self, int ifindex, _NMSettingWirelessWakeOnWLan wowl); +gboolean nm_platform_wifi_get_csme_conn_info(NMPlatform *self, + int ifindex, + NMPlatformCsmeConnInfo *out_conn_info); guint32 nm_platform_mesh_get_channel(NMPlatform *self, int ifindex); gboolean nm_platform_mesh_set_channel(NMPlatform *self, int ifindex, guint32 channel); diff --git a/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c b/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c index 2659414e11..8a56a02773 100644 --- a/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c +++ b/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c @@ -15,6 +15,8 @@ #include #include +#include "linux-headers/nl80211-vnd-intel.h" + #include "libnm-log-core/nm-logging.h" #include "libnm-platform/nm-netlink.h" #include "nm-wifi-utils-private.h" @@ -817,6 +819,90 @@ nla_put_failure: g_return_val_if_reached(FALSE); } +struct nl80211_csme_conn_info { + NMWifiUtilsNl80211 *self; + NMPlatformCsmeConnInfo *conn_info; +}; + +static int +nl80211_csme_conn_event_handler(struct nl_msg *msg, void *arg) +{ + struct nl80211_csme_conn_info *info = arg; + NMPlatformCsmeConnInfo *out_conn_info = info->conn_info; + NMWifiUtilsNl80211 *self = info->self; + struct genlmsghdr *gnlh = (void *) nlmsg_data(nlmsg_hdr(msg)); + struct nlattr *tb[NL80211_ATTR_MAX + 1]; + struct nlattr *data; + struct nlattr *attrs[NUM_IWL_MVM_VENDOR_ATTR]; + int err; + + static const struct nla_policy iwl_vendor_policy[NUM_IWL_MVM_VENDOR_ATTR] = { + [IWL_MVM_VENDOR_ATTR_AUTH_MODE] = {.type = NLA_U32}, + [IWL_MVM_VENDOR_ATTR_SSID] = {.type = NLA_UNSPEC, .maxlen = NM_IW_ESSID_MAX_SIZE}, + [IWL_MVM_VENDOR_ATTR_STA_CIPHER] = {.type = NLA_U32}, + [IWL_MVM_VENDOR_ATTR_CHANNEL_NUM] = {.type = NLA_U8}, + [IWL_MVM_VENDOR_ATTR_ADDR] = {.type = NLA_UNSPEC, .minlen = ETH_ALEN, .maxlen = ETH_ALEN}, + }; + + nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); + data = tb[NL80211_ATTR_VENDOR_DATA]; + + *out_conn_info = (NMPlatformCsmeConnInfo){}; + + err = nla_parse_nested(attrs, MAX_IWL_MVM_VENDOR_ATTR, data, iwl_vendor_policy); + if (err) { + _LOGD("IWL_MVM_VENDOR_CMD_GET_CSME_CONN_INFO Failed to parse CSME connection info: %s", + nm_strerror(err)); + return -EINVAL; + } + + if (attrs[IWL_MVM_VENDOR_ATTR_AUTH_MODE]) + out_conn_info->auth_mode = nla_get_u8(attrs[IWL_MVM_VENDOR_ATTR_AUTH_MODE]); + + if (attrs[IWL_MVM_VENDOR_ATTR_SSID]) + memcpy(out_conn_info->ssid, + nla_data(attrs[IWL_MVM_VENDOR_ATTR_SSID]), + nla_len(attrs[IWL_MVM_VENDOR_ATTR_SSID])); + + if (attrs[IWL_MVM_VENDOR_ATTR_STA_CIPHER]) + out_conn_info->sta_cipher = nla_get_u8(attrs[IWL_MVM_VENDOR_ATTR_STA_CIPHER]); + + if (attrs[IWL_MVM_VENDOR_ATTR_CHANNEL_NUM]) + out_conn_info->channel = nla_get_u8(attrs[IWL_MVM_VENDOR_ATTR_CHANNEL_NUM]); + + if (attrs[IWL_MVM_VENDOR_ATTR_ADDR]) + memcpy(&out_conn_info->addr, + nla_data(attrs[IWL_MVM_VENDOR_ATTR_ADDR]), + sizeof(out_conn_info->addr)); + + return NL_SKIP; +} + +static gboolean +wifi_nl80211_intel_vnd_get_csme_conn_info(NMWifiUtils *data, NMPlatformCsmeConnInfo *out_conn_info) +{ + NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; + nm_auto_nlmsg struct nl_msg *msg = NULL; + int err; + struct nl80211_csme_conn_info conn_info = { + .self = self, + .conn_info = out_conn_info, + }; + + msg = nl80211_alloc_msg(self, NL80211_CMD_VENDOR, 0); + NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_ID, INTEL_OUI); + NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_SUBCMD, IWL_MVM_VENDOR_CMD_GET_CSME_CONN_INFO); + + err = nl80211_send_and_recv(self, msg, nl80211_csme_conn_event_handler, &conn_info); + if (err < 0) + _LOGD("IWL_MVM_VENDOR_CMD_GET_CSME_CONN_INFO request failed: %s", nm_strerror(err)); + + return err >= 0; + +nla_put_failure: + g_return_val_if_reached(FALSE); +} + static void nm_wifi_utils_nl80211_init(NMWifiUtilsNl80211 *self) {} @@ -841,6 +927,7 @@ nm_wifi_utils_nl80211_class_init(NMWifiUtilsNl80211Class *klass) wifi_utils_class->get_mesh_channel = wifi_nl80211_get_mesh_channel; wifi_utils_class->set_mesh_channel = wifi_nl80211_set_mesh_channel; wifi_utils_class->set_mesh_ssid = wifi_nl80211_set_mesh_ssid; + wifi_utils_class->get_csme_conn_info = wifi_nl80211_intel_vnd_get_csme_conn_info; } NMWifiUtils * diff --git a/src/libnm-platform/wifi/nm-wifi-utils-private.h b/src/libnm-platform/wifi/nm-wifi-utils-private.h index 7461b65e73..c71963682e 100644 --- a/src/libnm-platform/wifi/nm-wifi-utils-private.h +++ b/src/libnm-platform/wifi/nm-wifi-utils-private.h @@ -7,6 +7,7 @@ #define __WIFI_UTILS_PRIVATE_H__ #include "nm-wifi-utils.h" +#include "libnm-platform/nm-platform.h" typedef struct { GObjectClass parent; @@ -53,6 +54,8 @@ typedef struct { gboolean (*set_mesh_ssid)(NMWifiUtils *data, const guint8 *ssid, gsize len); gboolean (*indicate_addressing_running)(NMWifiUtils *data, gboolean running); + + gboolean (*get_csme_conn_info)(NMWifiUtils *data, NMPlatformCsmeConnInfo *out_conn_info); } NMWifiUtilsClass; struct NMWifiUtils { diff --git a/src/libnm-platform/wifi/nm-wifi-utils.c b/src/libnm-platform/wifi/nm-wifi-utils.c index 1e484cfd1b..dd2a9ab60e 100644 --- a/src/libnm-platform/wifi/nm-wifi-utils.c +++ b/src/libnm-platform/wifi/nm-wifi-utils.c @@ -157,6 +157,17 @@ nm_wifi_utils_is_wifi(int dirfd, const char *ifname) return FALSE; } +gboolean +nm_wifi_utils_get_csme_conn_info(NMWifiUtils *data, NMPlatformCsmeConnInfo *out_conn_info) +{ + NMWifiUtilsClass *klass; + + g_return_val_if_fail(data != NULL, FALSE); + + klass = NM_WIFI_UTILS_GET_CLASS(data); + return klass->get_csme_conn_info ? klass->get_csme_conn_info(data, out_conn_info) : FALSE; +} + /* OLPC Mesh-only functions */ guint32 diff --git a/src/libnm-platform/wifi/nm-wifi-utils.h b/src/libnm-platform/wifi/nm-wifi-utils.h index be33b90ca8..327a9c24f1 100644 --- a/src/libnm-platform/wifi/nm-wifi-utils.h +++ b/src/libnm-platform/wifi/nm-wifi-utils.h @@ -63,6 +63,10 @@ _NMSettingWirelessWakeOnWLan nm_wifi_utils_get_wake_on_wlan(NMWifiUtils *data); gboolean nm_wifi_utils_set_wake_on_wlan(NMWifiUtils *data, _NMSettingWirelessWakeOnWLan wowl); +struct _NMPlatformCsmeConnInfo; +gboolean nm_wifi_utils_get_csme_conn_info(NMWifiUtils *data, + struct _NMPlatformCsmeConnInfo *out_conn_info); + /* OLPC Mesh-only functions */ guint32 nm_wifi_utils_get_mesh_channel(NMWifiUtils *data); From 965c55f0dac33faa512502ce56eb9fdcff226343 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 28 Feb 2022 22:28:41 +0200 Subject: [PATCH 3/3] platform: add Intel vendor command to get the device from CSME This will allow us to let CSME know that we are ready to connect and it can remove the "OS_NOT_OWNER" rfkill. --- src/libnm-platform/nm-linux-platform.c | 9 ++++++++ src/libnm-platform/nm-platform.c | 10 +++++++++ src/libnm-platform/nm-platform.h | 2 ++ .../wifi/nm-wifi-utils-nl80211.c | 22 +++++++++++++++++++ .../wifi/nm-wifi-utils-private.h | 2 ++ src/libnm-platform/wifi/nm-wifi-utils.c | 11 ++++++++++ src/libnm-platform/wifi/nm-wifi-utils.h | 2 ++ 7 files changed, 58 insertions(+) diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index 1c14c08b4a..e184ed4a2a 100644 --- a/src/libnm-platform/nm-linux-platform.c +++ b/src/libnm-platform/nm-linux-platform.c @@ -8544,6 +8544,14 @@ wifi_get_csme_conn_info(NMPlatform *platform, int ifindex, NMPlatformCsmeConnInf return nm_wifi_utils_get_csme_conn_info(wifi_data, out_conn_info); } +static gboolean +wifi_get_device_from_csme(NMPlatform *platform, int ifindex) +{ + WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); + + return nm_wifi_utils_get_device_from_csme(wifi_data); +} + /*****************************************************************************/ static gboolean @@ -9963,6 +9971,7 @@ nm_linux_platform_class_init(NMLinuxPlatformClass *klass) platform_class->wifi_get_wake_on_wlan = wifi_get_wake_on_wlan; platform_class->wifi_set_wake_on_wlan = wifi_set_wake_on_wlan; platform_class->wifi_get_csme_conn_info = wifi_get_csme_conn_info; + platform_class->wifi_get_device_from_csme = wifi_get_device_from_csme; platform_class->mesh_get_channel = mesh_get_channel; platform_class->mesh_set_channel = mesh_set_channel; diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index 52dc4779d2..f6baa6404f 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -3073,6 +3073,16 @@ nm_platform_wifi_get_csme_conn_info(NMPlatform *self, return klass->wifi_get_csme_conn_info(self, ifindex, out_conn_info); } +gboolean +nm_platform_wifi_get_device_from_csme(NMPlatform *self, int ifindex) +{ + _CHECK_SELF(self, klass, FALSE); + + g_return_val_if_fail(ifindex > 0, FALSE); + + return klass->wifi_get_device_from_csme(self, ifindex); +} + guint32 nm_platform_mesh_get_channel(NMPlatform *self, int ifindex) { diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h index 87441026c3..e10384d27a 100644 --- a/src/libnm-platform/nm-platform.h +++ b/src/libnm-platform/nm-platform.h @@ -1215,6 +1215,7 @@ typedef struct { gboolean (*wifi_get_csme_conn_info)(NMPlatform *self, int ifindex, NMPlatformCsmeConnInfo *out_conn_info); + gboolean (*wifi_get_device_from_csme)(NMPlatform *self, int ifindex); guint32 (*mesh_get_channel)(NMPlatform *self, int ifindex); gboolean (*mesh_set_channel)(NMPlatform *self, int ifindex, guint32 channel); @@ -2042,6 +2043,7 @@ nm_platform_wifi_set_wake_on_wlan(NMPlatform *self, int ifindex, _NMSettingWirel gboolean nm_platform_wifi_get_csme_conn_info(NMPlatform *self, int ifindex, NMPlatformCsmeConnInfo *out_conn_info); +gboolean nm_platform_wifi_get_device_from_csme(NMPlatform *self, int ifindex); guint32 nm_platform_mesh_get_channel(NMPlatform *self, int ifindex); gboolean nm_platform_mesh_set_channel(NMPlatform *self, int ifindex, guint32 channel); diff --git a/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c b/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c index 8a56a02773..b7e5c45af8 100644 --- a/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c +++ b/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c @@ -903,6 +903,27 @@ nla_put_failure: g_return_val_if_reached(FALSE); } +static gboolean +wifi_nl80211_intel_vnd_get_device_from_csme(NMWifiUtils *data) +{ + NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; + nm_auto_nlmsg struct nl_msg *msg = NULL; + int err; + + msg = nl80211_alloc_msg(self, NL80211_CMD_VENDOR, 0); + NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_ID, INTEL_OUI); + NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_SUBCMD, IWL_MVM_VENDOR_CMD_HOST_GET_OWNERSHIP); + + err = nl80211_send_and_recv(self, msg, NULL, NULL); + if (err < 0) + _LOGD("IWL_MVM_VENDOR_CMD_HOST_GET_OWNERSHIP request failed: %s", nm_strerror(err)); + + return err >= 0; + +nla_put_failure: + g_return_val_if_reached(FALSE); +} + static void nm_wifi_utils_nl80211_init(NMWifiUtilsNl80211 *self) {} @@ -928,6 +949,7 @@ nm_wifi_utils_nl80211_class_init(NMWifiUtilsNl80211Class *klass) wifi_utils_class->set_mesh_channel = wifi_nl80211_set_mesh_channel; wifi_utils_class->set_mesh_ssid = wifi_nl80211_set_mesh_ssid; wifi_utils_class->get_csme_conn_info = wifi_nl80211_intel_vnd_get_csme_conn_info; + wifi_utils_class->get_device_from_csme = wifi_nl80211_intel_vnd_get_device_from_csme; } NMWifiUtils * diff --git a/src/libnm-platform/wifi/nm-wifi-utils-private.h b/src/libnm-platform/wifi/nm-wifi-utils-private.h index c71963682e..7fe157f206 100644 --- a/src/libnm-platform/wifi/nm-wifi-utils-private.h +++ b/src/libnm-platform/wifi/nm-wifi-utils-private.h @@ -56,6 +56,8 @@ typedef struct { gboolean (*indicate_addressing_running)(NMWifiUtils *data, gboolean running); gboolean (*get_csme_conn_info)(NMWifiUtils *data, NMPlatformCsmeConnInfo *out_conn_info); + + gboolean (*get_device_from_csme)(NMWifiUtils *data); } NMWifiUtilsClass; struct NMWifiUtils { diff --git a/src/libnm-platform/wifi/nm-wifi-utils.c b/src/libnm-platform/wifi/nm-wifi-utils.c index dd2a9ab60e..08a8ec4ff3 100644 --- a/src/libnm-platform/wifi/nm-wifi-utils.c +++ b/src/libnm-platform/wifi/nm-wifi-utils.c @@ -168,6 +168,17 @@ nm_wifi_utils_get_csme_conn_info(NMWifiUtils *data, NMPlatformCsmeConnInfo *out_ return klass->get_csme_conn_info ? klass->get_csme_conn_info(data, out_conn_info) : FALSE; } +gboolean +nm_wifi_utils_get_device_from_csme(NMWifiUtils *data) +{ + NMWifiUtilsClass *klass; + + g_return_val_if_fail(data != NULL, FALSE); + + klass = NM_WIFI_UTILS_GET_CLASS(data); + return klass->get_device_from_csme ? klass->get_device_from_csme(data) : FALSE; +} + /* OLPC Mesh-only functions */ guint32 diff --git a/src/libnm-platform/wifi/nm-wifi-utils.h b/src/libnm-platform/wifi/nm-wifi-utils.h index 327a9c24f1..0d30c1a119 100644 --- a/src/libnm-platform/wifi/nm-wifi-utils.h +++ b/src/libnm-platform/wifi/nm-wifi-utils.h @@ -67,6 +67,8 @@ struct _NMPlatformCsmeConnInfo; gboolean nm_wifi_utils_get_csme_conn_info(NMWifiUtils *data, struct _NMPlatformCsmeConnInfo *out_conn_info); +gboolean nm_wifi_utils_get_device_from_csme(NMWifiUtils *data); + /* OLPC Mesh-only functions */ guint32 nm_wifi_utils_get_mesh_channel(NMWifiUtils *data);