diff --git a/NEWS b/NEWS index e2bdb9cb5c..5dd05ed1bd 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,7 @@ USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE! visible in nmcli via "nmcli -f all device show $DEV". * Deprecated 802-11-wireless and 802-11-wired property 'mac-address-blacklist' and introduced the 'mac-address-denylist' property. +* Fix detection of 6 GHz band capability for WiFi devices ============================================= NetworkManager-1.46 diff --git a/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c b/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c index 3b90d180ae..3c00898a27 100644 --- a/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c +++ b/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c @@ -567,6 +567,7 @@ struct nl80211_device_info { int phy; Nl80211Freq *freqs; int num_freqs; + int num_freqs_alloc; guint32 freq; guint32 caps; gboolean can_scan; @@ -610,7 +611,6 @@ nl80211_wiphy_info_handler(const struct nl_msg *msg, void *arg) struct nlattr *nl_freq; int rem_freq; int rem_band; - guint num_alloc; #ifdef NL80211_FREQUENCY_ATTR_NO_IR G_STATIC_ASSERT_EXPR(NL80211_FREQUENCY_ATTR_PASSIVE_SCAN == NL80211_FREQUENCY_ATTR_NO_IR @@ -622,22 +622,16 @@ nl80211_wiphy_info_handler(const struct nl_msg *msg, void *arg) if (nla_parse_arr(tb, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL) < 0) return NL_SKIP; - if (tb[NL80211_ATTR_WIPHY] == NULL || tb[NL80211_ATTR_WIPHY_BANDS] == NULL) + if (!tb[NL80211_ATTR_WIPHY]) return NL_SKIP; info->phy = nla_get_u32(tb[NL80211_ATTR_WIPHY]); if (tb[NL80211_ATTR_WIPHY_FREQ]) info->freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]); - else - info->freq = 0; - if (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]) { + if (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]) info->can_scan_ssid = nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]) > 0; - } else { - /* old kernel that only had mac80211, so assume it can */ - info->can_scan_ssid = TRUE; - } if (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) { struct nlattr *nl_cmd; @@ -664,51 +658,57 @@ nl80211_wiphy_info_handler(const struct nl_msg *msg, void *arg) } } - /* Read supported frequencies */ - num_alloc = 32; - info->num_freqs = 0; - info->freqs = g_new(Nl80211Freq, num_alloc); + if (tb[NL80211_ATTR_WIPHY_BANDS]) { + /* Read supported frequencies */ - nla_for_each_nested (nl_band, tb[NL80211_ATTR_WIPHY_BANDS], rem_band) { - if (nla_parse_nested_arr(tb_band, nl_band, NULL) < 0) - return NL_SKIP; + if (!info->freqs) { + info->num_freqs = 0; + info->num_freqs_alloc = 32; + info->freqs = g_new(Nl80211Freq, info->num_freqs_alloc); + } - nla_for_each_nested (nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) { - Nl80211Freq *f; + nla_for_each_nested (nl_band, tb[NL80211_ATTR_WIPHY_BANDS], rem_band) { + if (nla_parse_nested_arr(tb_band, nl_band, NULL) < 0) + return NL_SKIP; - if (nla_parse_nested_arr(tb_freq, nl_freq, freq_policy) < 0) + if (!tb_band[NL80211_BAND_ATTR_FREQS]) continue; - if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) - continue; + nla_for_each_nested (nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) { + Nl80211Freq *f; - if (info->num_freqs >= num_alloc) { - num_alloc *= 2; - info->freqs = g_renew(Nl80211Freq, info->freqs, num_alloc); + if (nla_parse_nested_arr(tb_freq, nl_freq, freq_policy) < 0) + continue; + + if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) + continue; + + if (info->num_freqs >= info->num_freqs_alloc) { + info->num_freqs_alloc *= 2; + info->freqs = g_renew(Nl80211Freq, info->freqs, info->num_freqs_alloc); + } + + f = &info->freqs[info->num_freqs]; + *f = (Nl80211Freq){ + .freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]), + .disabled = !!tb_freq[NL80211_FREQUENCY_ATTR_DISABLED], + .no_ir = !!tb_freq[NL80211_FREQUENCY_ATTR_NO_IR], + }; + + info->caps |= _NM_WIFI_DEVICE_CAP_FREQ_VALID; + + if (f->freq >= 2401 && f->freq <= 2495) + info->caps |= _NM_WIFI_DEVICE_CAP_FREQ_2GHZ; + if (f->freq >= 5150 && f->freq < 5950) + info->caps |= _NM_WIFI_DEVICE_CAP_FREQ_5GHZ; + if (f->freq >= 5950 && f->freq <= 7125) + info->caps |= _NM_WIFI_DEVICE_CAP_FREQ_6GHZ; + + info->num_freqs++; } - - f = &info->freqs[info->num_freqs]; - *f = (Nl80211Freq){ - .freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]), - .disabled = !!tb_freq[NL80211_FREQUENCY_ATTR_DISABLED], - .no_ir = !!tb_freq[NL80211_FREQUENCY_ATTR_NO_IR], - }; - - info->caps |= _NM_WIFI_DEVICE_CAP_FREQ_VALID; - - if (f->freq >= 2401 && f->freq <= 2495) - info->caps |= _NM_WIFI_DEVICE_CAP_FREQ_2GHZ; - if (f->freq >= 5150 && f->freq < 5950) - info->caps |= _NM_WIFI_DEVICE_CAP_FREQ_5GHZ; - if (f->freq >= 5950 && f->freq <= 7125) - info->caps |= _NM_WIFI_DEVICE_CAP_FREQ_6GHZ; - - info->num_freqs++; } } - info->freqs = g_renew(Nl80211Freq, info->freqs, info->num_freqs); - /* Read security/encryption support */ if (tb[NL80211_ATTR_CIPHER_SUITES]) { guint32 *ciphers = nla_data(tb[NL80211_ATTR_CIPHER_SUITES]); @@ -874,7 +874,10 @@ nm_wifi_utils_nl80211_new(struct nl_sock *genl, guint16 genl_family_id, int ifin self->phy = -1; - msg = nl80211_alloc_msg(self, NL80211_CMD_GET_WIPHY, 0); + msg = nl80211_alloc_msg(self, NL80211_CMD_GET_WIPHY, NLM_F_DUMP); + NLA_PUT_FLAG(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP); + + device_info.can_scan_ssid = TRUE; device_info.self = self; if (nl80211_send_and_recv(self, msg, nl80211_wiphy_info_handler, &device_info) < 0) { @@ -882,6 +885,10 @@ nm_wifi_utils_nl80211_new(struct nl_sock *genl, guint16 genl_family_id, int ifin return NULL; } + if (device_info.freqs) { + device_info.freqs = g_renew(Nl80211Freq, device_info.freqs, device_info.num_freqs); + } + if (!device_info.success) { _LOGD("NL80211_CMD_GET_WIPHY request indicated failure"); return NULL; @@ -915,4 +922,7 @@ nm_wifi_utils_nl80211_new(struct nl_sock *genl, guint16 genl_family_id, int ifin _LOGD("using nl80211 for Wi-Fi device control"); return (NMWifiUtils *) g_steal_pointer(&self); + +nla_put_failure: + g_return_val_if_reached(NULL); }