mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-02 22:38:01 +00:00
wifi: fix enumeration of 6 GHz channels from wiphy
Command NL80211_CMD_GET_WIPHY without any flag only returns channels in the 2 GHz and 5 GHz bands, for backwards compatibility with old userspace tools. To get the full list we need to pass attribute NL80211_ATTR_SPLIT_WIPHY_DUMP (added in Linux 3.9 released in 2013), and allow the handler to be called multiple times. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1500
This commit is contained in:
parent
8ca7433a14
commit
4cd4ab518e
1
NEWS
1
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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue