diff --git a/src/core/devices/wifi/nm-wifi-ap.c b/src/core/devices/wifi/nm-wifi-ap.c index 3e7589721b..4a05c08763 100644 --- a/src/core/devices/wifi/nm-wifi-ap.c +++ b/src/core/devices/wifi/nm-wifi-ap.c @@ -38,7 +38,8 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMWifiAP, PROP_MAX_BITRATE, PROP_BANDWIDTH, PROP_STRENGTH, - PROP_LAST_SEEN, ); + PROP_LAST_SEEN, + PROP_WIFI_GENERATION, ); struct _NMWifiAPPrivate { /* Scanned or cached values */ @@ -57,6 +58,7 @@ struct _NMWifiAPPrivate { NM80211ApFlags flags; /* General flags */ NM80211ApSecurityFlags wpa_flags; /* WPA-related flags */ NM80211ApSecurityFlags rsn_flags; /* RSN (WPA2) -related flags */ + NMWifiGeneration wifi_generation; bool metered : 1; @@ -367,6 +369,19 @@ nm_wifi_ap_set_last_seen(NMWifiAP *ap, gint32 last_seen_msec) return FALSE; } +static gboolean +nm_wifi_ap_set_wifi_generation(NMWifiAP *ap, NMWifiGeneration wifi_generation) +{ + NMWifiAPPrivate *priv = NM_WIFI_AP_GET_PRIVATE(ap); + + if (priv->wifi_generation != wifi_generation) { + priv->wifi_generation = wifi_generation; + _notify(ap, PROP_WIFI_GENERATION); + return TRUE; + } + return FALSE; +} + gboolean nm_wifi_ap_get_metered(const NMWifiAP *self) { @@ -431,6 +446,8 @@ nm_wifi_ap_update_from_properties(NMWifiAP *ap, const NMSupplicantBssInfo *bss_i changed |= nm_wifi_ap_set_wpa_flags(ap, bss_info->wpa_flags); changed |= nm_wifi_ap_set_rsn_flags(ap, bss_info->rsn_flags); + changed |= nm_wifi_ap_set_wifi_generation(ap, bss_info->wifi_generation); + changed |= nm_wifi_ap_set_last_seen(ap, bss_info->last_seen_msec); changed |= nm_wifi_ap_set_fake(ap, FALSE); @@ -718,6 +735,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) 1) : -1); break; + case PROP_WIFI_GENERATION: + g_value_set_uint(value, priv->wifi_generation); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -737,11 +757,12 @@ nm_wifi_ap_init(NMWifiAP *self) c_list_init(&self->aps_lst); - priv->mode = _NM_802_11_MODE_INFRA; - priv->flags = NM_802_11_AP_FLAGS_NONE; - priv->wpa_flags = NM_802_11_AP_SEC_NONE; - priv->rsn_flags = NM_802_11_AP_SEC_NONE; - priv->last_seen_msec = G_MININT64; + priv->mode = _NM_802_11_MODE_INFRA; + priv->flags = NM_802_11_AP_FLAGS_NONE; + priv->wpa_flags = NM_802_11_AP_SEC_NONE; + priv->rsn_flags = NM_802_11_AP_SEC_NONE; + priv->last_seen_msec = G_MININT64; + priv->wifi_generation = NM_WIFI_GENERATION_LEGACY; } NMWifiAP * @@ -898,9 +919,10 @@ static const NMDBusInterfaceInfoExtended interface_info_access_point = { NM_WIFI_AP_MAX_BITRATE), NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Bandwidth", "u", NM_WIFI_AP_BANDWIDTH), NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Strength", "y", NM_WIFI_AP_STRENGTH), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("LastSeen", - "i", - NM_WIFI_AP_LAST_SEEN), ), ), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("LastSeen", "i", NM_WIFI_AP_LAST_SEEN), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("WifiGeneration", + "u", + NM_WIFI_AP_WIFI_GENERATION), ), ), }; static void @@ -1003,6 +1025,15 @@ nm_wifi_ap_class_init(NMWifiAPClass *ap_class) -1, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_WIFI_GENERATION] = + g_param_spec_uint(NM_WIFI_AP_WIFI_GENERATION, + "", + "", + NM_WIFI_GENERATION_LEGACY, + G_MAXUINT, + NM_WIFI_GENERATION_LEGACY, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_BANDWIDTH] = g_param_spec_uint(NM_WIFI_AP_BANDWIDTH, "", "", diff --git a/src/core/devices/wifi/nm-wifi-ap.h b/src/core/devices/wifi/nm-wifi-ap.h index 0f229640b5..4dc614ec84 100644 --- a/src/core/devices/wifi/nm-wifi-ap.h +++ b/src/core/devices/wifi/nm-wifi-ap.h @@ -19,17 +19,18 @@ #define NM_IS_WIFI_AP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_WIFI_AP)) #define NM_WIFI_AP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_WIFI_AP, NMWifiAPClass)) -#define NM_WIFI_AP_FLAGS "flags" -#define NM_WIFI_AP_WPA_FLAGS "wpa-flags" -#define NM_WIFI_AP_RSN_FLAGS "rsn-flags" -#define NM_WIFI_AP_SSID "ssid" -#define NM_WIFI_AP_FREQUENCY "frequency" -#define NM_WIFI_AP_HW_ADDRESS "hw-address" -#define NM_WIFI_AP_MODE "mode" -#define NM_WIFI_AP_MAX_BITRATE "max-bitrate" -#define NM_WIFI_AP_BANDWIDTH "bandwidth" -#define NM_WIFI_AP_STRENGTH "strength" -#define NM_WIFI_AP_LAST_SEEN "last-seen" +#define NM_WIFI_AP_FLAGS "flags" +#define NM_WIFI_AP_WPA_FLAGS "wpa-flags" +#define NM_WIFI_AP_RSN_FLAGS "rsn-flags" +#define NM_WIFI_AP_SSID "ssid" +#define NM_WIFI_AP_FREQUENCY "frequency" +#define NM_WIFI_AP_HW_ADDRESS "hw-address" +#define NM_WIFI_AP_MODE "mode" +#define NM_WIFI_AP_MAX_BITRATE "max-bitrate" +#define NM_WIFI_AP_BANDWIDTH "bandwidth" +#define NM_WIFI_AP_STRENGTH "strength" +#define NM_WIFI_AP_LAST_SEEN "last-seen" +#define NM_WIFI_AP_WIFI_GENERATION "wifi-generation" typedef struct { NMDBusObject parent; diff --git a/src/core/nm-core-utils.c b/src/core/nm-core-utils.c index 5404ecb9ce..9b2b310297 100644 --- a/src/core/nm-core-utils.c +++ b/src/core/nm-core-utils.c @@ -4901,14 +4901,19 @@ get_bandwidth_vht(const guint8 *bytes, guint len, guint32 *out_bandwidth) #define WLAN_EID_VHT_CAPABILITY 191 #define WLAN_EID_VHT_OPERATION 192 #define WLAN_EID_VENDOR_SPECIFIC 221 +#define WLAN_EID_EXTENSION 255 + +#define WLAN_EID_EXT_HE_CAPABILITY 35 +#define WLAN_EID_EXT_EHT_CAPABILITY 108 void -nm_wifi_utils_parse_ies(const guint8 *bytes, - gsize len, - guint32 *out_max_rate, - guint32 *out_bandwidth, - gboolean *out_metered, - gboolean *out_owe_transition_mode) +nm_wifi_utils_parse_ies(const guint8 *bytes, + gsize len, + guint32 *out_max_rate, + guint32 *out_bandwidth, + gboolean *out_metered, + gboolean *out_owe_transition_mode, + NMWifiGeneration *out_wifi_generation) { guint8 id, elem_len; guint32 m; @@ -4917,6 +4922,7 @@ nm_wifi_utils_parse_ies(const guint8 *bytes, NM_SET_OUT(out_bandwidth, 0); NM_SET_OUT(out_metered, FALSE); NM_SET_OUT(out_owe_transition_mode, FALSE); + NM_SET_OUT(out_wifi_generation, NM_WIFI_GENERATION_LEGACY); while (len) { if (len < 2) @@ -4931,6 +4937,9 @@ nm_wifi_utils_parse_ies(const guint8 *bytes, switch (id) { case WLAN_EID_HT_CAPABILITY: + if (out_wifi_generation && *out_wifi_generation < NM_WIFI_GENERATION_WIFI_4) + *out_wifi_generation = NM_WIFI_GENERATION_WIFI_4; + if (out_max_rate) { if (get_max_rate_ht(bytes, elem_len, &m)) *out_max_rate = NM_MAX(*out_max_rate, m); @@ -4941,6 +4950,9 @@ nm_wifi_utils_parse_ies(const guint8 *bytes, get_bandwidth_ht(bytes, elem_len, out_bandwidth); break; case WLAN_EID_VHT_CAPABILITY: + if (out_wifi_generation && *out_wifi_generation < NM_WIFI_GENERATION_WIFI_5) + *out_wifi_generation = NM_WIFI_GENERATION_WIFI_5; + if (out_max_rate) { if (get_max_rate_vht(bytes, elem_len, &m)) *out_max_rate = NM_MAX(*out_max_rate, m); @@ -4950,6 +4962,19 @@ nm_wifi_utils_parse_ies(const guint8 *bytes, if (out_bandwidth) get_bandwidth_vht(bytes, elem_len, out_bandwidth); break; + case WLAN_EID_EXTENSION: + if (out_wifi_generation && elem_len >= 1) { + guint8 ext_id = bytes[0]; + + if (ext_id == WLAN_EID_EXT_HE_CAPABILITY) { + if (*out_wifi_generation < NM_WIFI_GENERATION_WIFI_6) + *out_wifi_generation = NM_WIFI_GENERATION_WIFI_6; + } else if (ext_id == WLAN_EID_EXT_EHT_CAPABILITY) { + if (*out_wifi_generation < NM_WIFI_GENERATION_WIFI_7) + *out_wifi_generation = NM_WIFI_GENERATION_WIFI_7; + } + } + break; case WLAN_EID_VENDOR_SPECIFIC: if (len == 8 && bytes[0] == 0x00 /* OUI: Microsoft */ && bytes[1] == 0x50 && bytes[2] == 0xf2 diff --git a/src/core/nm-core-utils.h b/src/core/nm-core-utils.h index cccccae636..12bbdda201 100644 --- a/src/core/nm-core-utils.h +++ b/src/core/nm-core-utils.h @@ -458,12 +458,13 @@ const char *nm_utils_parse_dns_domain(const char *domain, gboolean *is_routing); /*****************************************************************************/ -void nm_wifi_utils_parse_ies(const guint8 *bytes, - gsize len, - guint32 *out_max_rate, - guint32 *out_bandwidth, - gboolean *out_metered, - gboolean *out_owe_transition_mode); +void nm_wifi_utils_parse_ies(const guint8 *bytes, + gsize len, + guint32 *out_max_rate, + guint32 *out_bandwidth, + gboolean *out_metered, + gboolean *out_owe_transition_mode, + NMWifiGeneration *out_wifi_generation); guint8 nm_wifi_utils_level_to_quality(int val); diff --git a/src/core/supplicant/nm-supplicant-interface.c b/src/core/supplicant/nm-supplicant-interface.c index 4476c7015a..c266bd1f42 100644 --- a/src/core/supplicant/nm-supplicant-interface.c +++ b/src/core/supplicant/nm-supplicant-interface.c @@ -11,6 +11,7 @@ #include #include +#include "core/nm-core-utils.h" #include "NetworkManagerUtils.h" #include "libnm-core-intern/nm-core-internal.h" #include "libnm-glib-aux/nm-c-list.h" @@ -765,10 +766,11 @@ _bss_info_properties_changed(NMSupplicantInterface *self, v_v = nm_g_variant_lookup_value(properties, "IEs", G_VARIANT_TYPE_BYTESTRING); if (v_v) { - gboolean p_owe_transition_mode; - gboolean p_metered; - guint32 rate; - guint32 bandwidth; + gboolean p_owe_transition_mode; + gboolean p_metered; + guint32 rate; + guint32 bandwidth; + NMWifiGeneration p_wifi_generation; arr_data = g_variant_get_fixed_array(v_v, &arr_len, 1); nm_wifi_utils_parse_ies(arr_data, @@ -776,7 +778,8 @@ _bss_info_properties_changed(NMSupplicantInterface *self, &rate, &bandwidth, &p_metered, - &p_owe_transition_mode); + &p_owe_transition_mode, + &p_wifi_generation); p_max_rate = NM_MAX(p_max_rate, rate); p_max_rate_has = TRUE; g_variant_unref(v_v); @@ -786,8 +789,9 @@ _bss_info_properties_changed(NMSupplicantInterface *self, else bss_info->rsn_flags &= ~NM_802_11_AP_SEC_KEY_MGMT_OWE_TM; - bss_info->metered = p_metered; - bss_info->bandwidth = bandwidth; + bss_info->metered = p_metered; + bss_info->bandwidth = bandwidth; + bss_info->wifi_generation = (guint8) p_wifi_generation; } if (p_max_rate_has) diff --git a/src/core/supplicant/nm-supplicant-types.h b/src/core/supplicant/nm-supplicant-types.h index 870a53c31f..3fc90721f8 100644 --- a/src/core/supplicant/nm-supplicant-types.h +++ b/src/core/supplicant/nm-supplicant-types.h @@ -195,6 +195,8 @@ typedef struct _NMSupplicantBssInfo { bool _bss_dirty : 1; + guint8 wifi_generation; /* NMWifiGeneration */ + } NMSupplicantBssInfo; typedef struct _NMSupplicantPeerInfo { diff --git a/src/libnm-client-impl/libnm.ver b/src/libnm-client-impl/libnm.ver index 1ac68586e4..d1beccfa53 100644 --- a/src/libnm-client-impl/libnm.ver +++ b/src/libnm-client-impl/libnm.ver @@ -2096,7 +2096,9 @@ global: libnm_1_58_0 { global: + nm_access_point_get_wifi_generation; nm_utils_wifi_6ghz_freqs; nm_utils_wifi_freq_to_band; nm_wifi_band_get_type; + nm_wifi_generation_get_type; } libnm_1_56_0; \ No newline at end of file diff --git a/src/libnm-client-impl/nm-access-point.c b/src/libnm-client-impl/nm-access-point.c index 994c7a0f1a..41ca5b50a4 100644 --- a/src/libnm-client-impl/nm-access-point.c +++ b/src/libnm-client-impl/nm-access-point.c @@ -34,20 +34,22 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMAccessPoint, PROP_BANDWIDTH, PROP_STRENGTH, PROP_BSSID, - PROP_LAST_SEEN, ); + PROP_LAST_SEEN, + PROP_WIFI_GENERATION, ); typedef struct { - GBytes *ssid; - char *bssid; - guint32 flags; - guint32 wpa_flags; - guint32 rsn_flags; - guint32 frequency; - guint32 mode; - guint32 max_bitrate; - guint32 bandwidth; - gint32 last_seen; - guint8 strength; + GBytes *ssid; + char *bssid; + guint32 flags; + guint32 wpa_flags; + guint32 rsn_flags; + guint32 frequency; + guint32 mode; + guint32 max_bitrate; + guint32 bandwidth; + gint32 last_seen; + guint8 strength; + NMWifiGeneration wifi_generation; } NMAccessPointPrivate; struct _NMAccessPoint { @@ -256,6 +258,24 @@ nm_access_point_get_last_seen(NMAccessPoint *ap) } NM_BACKPORT_SYMBOL(libnm_1_0_6, int, nm_access_point_get_last_seen, (NMAccessPoint * ap), (ap)); +/** + * nm_access_point_get_wifi_generation: + * @ap: a #NMAccessPoint + * + * Gets the Wi-Fi Generation (Wi-Fi 4, Wi-Fi 5, etc.) of the access point. + * + * Returns: the Wi-Fi Generation + * + * Since: 1.58 + **/ +NMWifiGeneration +nm_access_point_get_wifi_generation(NMAccessPoint *ap) +{ + g_return_val_if_fail(NM_IS_ACCESS_POINT(ap), NM_WIFI_GENERATION_LEGACY); + + return NM_ACCESS_POINT_GET_PRIVATE(ap)->wifi_generation; +} + /** * nm_access_point_connection_valid: * @ap: an #NMAccessPoint to validate @connection against @@ -496,6 +516,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) case PROP_LAST_SEEN: g_value_set_int(value, nm_access_point_get_last_seen(ap)); break; + case PROP_WIFI_GENERATION: + g_value_set_uint(value, nm_access_point_get_wifi_generation(ap)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -523,6 +546,10 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_accesspoint = NML_DBUS_META_IFACE NML_DBUS_META_PROPERTY_INIT_U("RsnFlags", PROP_RSN_FLAGS, NMAccessPoint, _priv.rsn_flags), NML_DBUS_META_PROPERTY_INIT_AY("Ssid", PROP_SSID, NMAccessPoint, _priv.ssid), NML_DBUS_META_PROPERTY_INIT_Y("Strength", PROP_STRENGTH, NMAccessPoint, _priv.strength), + NML_DBUS_META_PROPERTY_INIT_U("WifiGeneration", + PROP_WIFI_GENERATION, + NMAccessPoint, + _priv.wifi_generation), NML_DBUS_META_PROPERTY_INIT_U("WpaFlags", PROP_WPA_FLAGS, NMAccessPoint, @@ -693,5 +720,21 @@ nm_access_point_class_init(NMAccessPointClass *ap_class) -1, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + /** + * NMAccessPoint:wifi-generation: + * + * The Wi-Fi generation of the access point. + * + * Since: 1.58 + **/ + obj_properties[PROP_WIFI_GENERATION] = + g_param_spec_uint(NM_ACCESS_POINT_WIFI_GENERATION, + "", + "", + NM_WIFI_GENERATION_LEGACY, + NM_WIFI_GENERATION_WIFI_7, + NM_WIFI_GENERATION_LEGACY, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + _nml_dbus_meta_class_init_with_properties(object_class, &_nml_dbus_meta_iface_nm_accesspoint); } diff --git a/src/libnm-client-public/nm-access-point.h b/src/libnm-client-public/nm-access-point.h index f2cc1a4cc5..afa759eb91 100644 --- a/src/libnm-client-public/nm-access-point.h +++ b/src/libnm-client-public/nm-access-point.h @@ -25,17 +25,18 @@ G_BEGIN_DECLS #define NM_ACCESS_POINT_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_ACCESS_POINT, NMAccessPointClass)) -#define NM_ACCESS_POINT_FLAGS "flags" -#define NM_ACCESS_POINT_WPA_FLAGS "wpa-flags" -#define NM_ACCESS_POINT_RSN_FLAGS "rsn-flags" -#define NM_ACCESS_POINT_SSID "ssid" -#define NM_ACCESS_POINT_BSSID "bssid" -#define NM_ACCESS_POINT_FREQUENCY "frequency" -#define NM_ACCESS_POINT_MODE "mode" -#define NM_ACCESS_POINT_MAX_BITRATE "max-bitrate" -#define NM_ACCESS_POINT_STRENGTH "strength" -#define NM_ACCESS_POINT_LAST_SEEN "last-seen" -#define NM_ACCESS_POINT_BANDWIDTH "bandwidth" +#define NM_ACCESS_POINT_FLAGS "flags" +#define NM_ACCESS_POINT_WPA_FLAGS "wpa-flags" +#define NM_ACCESS_POINT_RSN_FLAGS "rsn-flags" +#define NM_ACCESS_POINT_SSID "ssid" +#define NM_ACCESS_POINT_BSSID "bssid" +#define NM_ACCESS_POINT_FREQUENCY "frequency" +#define NM_ACCESS_POINT_MODE "mode" +#define NM_ACCESS_POINT_MAX_BITRATE "max-bitrate" +#define NM_ACCESS_POINT_STRENGTH "strength" +#define NM_ACCESS_POINT_LAST_SEEN "last-seen" +#define NM_ACCESS_POINT_BANDWIDTH "bandwidth" +#define NM_ACCESS_POINT_WIFI_GENERATION "wifi-generation" /* DEPRECATED */ #define NM_ACCESS_POINT_HW_ADDRESS "hw-address" @@ -63,6 +64,9 @@ int nm_access_point_get_last_seen(NMAccessPoint *ap); NM_AVAILABLE_IN_1_46 guint32 nm_access_point_get_bandwidth(NMAccessPoint *ap); +NM_AVAILABLE_IN_1_58 +NMWifiGeneration nm_access_point_get_wifi_generation(NMAccessPoint *ap); + GPtrArray *nm_access_point_filter_connections(NMAccessPoint *ap, const GPtrArray *connections); gboolean nm_access_point_connection_valid(NMAccessPoint *ap, NMConnection *connection); diff --git a/src/libnm-core-public/nm-dbus-interface.h b/src/libnm-core-public/nm-dbus-interface.h index 42bff04ae0..63ec17746a 100644 --- a/src/libnm-core-public/nm-dbus-interface.h +++ b/src/libnm-core-public/nm-dbus-interface.h @@ -418,6 +418,26 @@ typedef enum /*< underscore_name=nm_802_11_ap_security_flags, flags >*/ { NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192 = 0x00002000, } NM80211ApSecurityFlags; +/** + * NMWifiGeneration: + * @NM_WIFI_GENERATION_LEGACY: pre-Wi-Fi 4 (802.11a/b/g) + * @NM_WIFI_GENERATION_WIFI_4: Wi-Fi 4 (802.11n) + * @NM_WIFI_GENERATION_WIFI_5: Wi-Fi 5 (802.11ac) + * @NM_WIFI_GENERATION_WIFI_6: Wi-Fi 6 (802.11ax) + * @NM_WIFI_GENERATION_WIFI_7: Wi-Fi 7 (802.11be) + * + * 802.11 Wi-Fi generation. + * + * Since: 1.58 + */ +typedef enum { + NM_WIFI_GENERATION_LEGACY = 0, + NM_WIFI_GENERATION_WIFI_4 = 4, + NM_WIFI_GENERATION_WIFI_5 = 5, + NM_WIFI_GENERATION_WIFI_6 = 6, + NM_WIFI_GENERATION_WIFI_7 = 7, +} NMWifiGeneration; + /** * NM80211Mode: * @NM_802_11_MODE_UNKNOWN: the device or access point mode is unknown